sheepdog: Support .bdrv_co_create
This adds the .bdrv_co_create driver callback to sheepdog, which enables image creation over QMP. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
		
							parent
							
								
									a595e4bcca
								
							
						
					
					
						commit
						63fd65a0a5
					
				
							
								
								
									
										243
									
								
								block/sheepdog.c
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								block/sheepdog.c
									
									
									
									
									
								
							@ -15,8 +15,10 @@
 | 
				
			|||||||
#include "qemu/osdep.h"
 | 
					#include "qemu/osdep.h"
 | 
				
			||||||
#include "qapi/error.h"
 | 
					#include "qapi/error.h"
 | 
				
			||||||
#include "qapi/qapi-visit-sockets.h"
 | 
					#include "qapi/qapi-visit-sockets.h"
 | 
				
			||||||
 | 
					#include "qapi/qapi-visit-block-core.h"
 | 
				
			||||||
#include "qapi/qmp/qdict.h"
 | 
					#include "qapi/qmp/qdict.h"
 | 
				
			||||||
#include "qapi/qobject-input-visitor.h"
 | 
					#include "qapi/qobject-input-visitor.h"
 | 
				
			||||||
 | 
					#include "qapi/qobject-output-visitor.h"
 | 
				
			||||||
#include "qemu/uri.h"
 | 
					#include "qemu/uri.h"
 | 
				
			||||||
#include "qemu/error-report.h"
 | 
					#include "qemu/error-report.h"
 | 
				
			||||||
#include "qemu/option.h"
 | 
					#include "qemu/option.h"
 | 
				
			||||||
@ -533,23 +535,6 @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
 | 
				
			|||||||
    qemu_co_mutex_unlock(&s->queue_lock);
 | 
					    qemu_co_mutex_unlock(&s->queue_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SocketAddress *sd_socket_address(const char *path,
 | 
					 | 
				
			||||||
                                        const char *host, const char *port)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    SocketAddress *addr = g_new0(SocketAddress, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (path) {
 | 
					 | 
				
			||||||
        addr->type = SOCKET_ADDRESS_TYPE_UNIX;
 | 
					 | 
				
			||||||
        addr->u.q_unix.path = g_strdup(path);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        addr->type = SOCKET_ADDRESS_TYPE_INET;
 | 
					 | 
				
			||||||
        addr->u.inet.host = g_strdup(host ?: SD_DEFAULT_ADDR);
 | 
					 | 
				
			||||||
        addr->u.inet.port = g_strdup(port ?: stringify(SD_DEFAULT_PORT));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return addr;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static SocketAddress *sd_server_config(QDict *options, Error **errp)
 | 
					static SocketAddress *sd_server_config(QDict *options, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QDict *server = NULL;
 | 
					    QDict *server = NULL;
 | 
				
			||||||
@ -1882,6 +1867,44 @@ out_with_err_set:
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int sd_create_prealloc(BlockdevOptionsSheepdog *location, int64_t size,
 | 
				
			||||||
 | 
					                              Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BlockDriverState *bs;
 | 
				
			||||||
 | 
					    Visitor *v;
 | 
				
			||||||
 | 
					    QObject *obj = NULL;
 | 
				
			||||||
 | 
					    QDict *qdict;
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    v = qobject_output_visitor_new(&obj);
 | 
				
			||||||
 | 
					    visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &local_err);
 | 
				
			||||||
 | 
					    visit_free(v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (local_err) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					        qobject_decref(obj);
 | 
				
			||||||
 | 
					        return -EINVAL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qdict = qobject_to_qdict(obj);
 | 
				
			||||||
 | 
					    qdict_flatten(qdict);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qdict_put_str(qdict, "driver", "sheepdog");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bs = bdrv_open(NULL, NULL, qdict, BDRV_O_PROTOCOL | BDRV_O_RDWR, errp);
 | 
				
			||||||
 | 
					    if (bs == NULL) {
 | 
				
			||||||
 | 
					        ret = -EIO;
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = sd_prealloc(bs, 0, size, errp);
 | 
				
			||||||
 | 
					fail:
 | 
				
			||||||
 | 
					    bdrv_unref(bs);
 | 
				
			||||||
 | 
					    QDECREF(qdict);
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
 | 
					static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct SheepdogInode *inode = &s->inode;
 | 
					    struct SheepdogInode *inode = &s->inode;
 | 
				
			||||||
@ -1934,9 +1957,9 @@ static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
 | 
				
			|||||||
 * # create a erasure coded vdi with x data strips and y parity strips
 | 
					 * # 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)
 | 
					 * -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)
 | 
					static SheepdogRedundancy *parse_redundancy_str(const char *opt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct SheepdogRedundancy redundancy;
 | 
					    SheepdogRedundancy *redundancy;
 | 
				
			||||||
    const char *n1, *n2;
 | 
					    const char *n1, *n2;
 | 
				
			||||||
    long copy, parity;
 | 
					    long copy, parity;
 | 
				
			||||||
    char p[10];
 | 
					    char p[10];
 | 
				
			||||||
@ -1947,26 +1970,27 @@ static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
 | 
				
			|||||||
    n2 = strtok(NULL, ":");
 | 
					    n2 = strtok(NULL, ":");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!n1) {
 | 
					    if (!n1) {
 | 
				
			||||||
        return -EINVAL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qemu_strtol(n1, NULL, 10, ©);
 | 
					    ret = qemu_strtol(n1, NULL, 10, ©);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        return ret;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    redundancy = g_new0(SheepdogRedundancy, 1);
 | 
				
			||||||
    if (!n2) {
 | 
					    if (!n2) {
 | 
				
			||||||
        redundancy = (SheepdogRedundancy) {
 | 
					        *redundancy = (SheepdogRedundancy) {
 | 
				
			||||||
            .type               = SHEEPDOG_REDUNDANCY_TYPE_FULL,
 | 
					            .type               = SHEEPDOG_REDUNDANCY_TYPE_FULL,
 | 
				
			||||||
            .u.full.copies      = copy,
 | 
					            .u.full.copies      = copy,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        ret = qemu_strtol(n2, NULL, 10, &parity);
 | 
					        ret = qemu_strtol(n2, NULL, 10, &parity);
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
            return ret;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        redundancy = (SheepdogRedundancy) {
 | 
					        *redundancy = (SheepdogRedundancy) {
 | 
				
			||||||
            .type               = SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED,
 | 
					            .type               = SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED,
 | 
				
			||||||
            .u.erasure_coded    = {
 | 
					            .u.erasure_coded    = {
 | 
				
			||||||
                .data_strips    = copy,
 | 
					                .data_strips    = copy,
 | 
				
			||||||
@ -1975,17 +1999,19 @@ static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return parse_redundancy(s, &redundancy);
 | 
					    return redundancy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
 | 
					static int parse_block_size_shift(BDRVSheepdogState *s,
 | 
				
			||||||
 | 
					                                  BlockdevCreateOptionsSheepdog *opts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct SheepdogInode *inode = &s->inode;
 | 
					    struct SheepdogInode *inode = &s->inode;
 | 
				
			||||||
    uint64_t object_size;
 | 
					    uint64_t object_size;
 | 
				
			||||||
    int obj_order;
 | 
					    int obj_order;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object_size = qemu_opt_get_size_del(opt, BLOCK_OPT_OBJECT_SIZE, 0);
 | 
					    if (opts->has_object_size) {
 | 
				
			||||||
    if (object_size) {
 | 
					        object_size = opts->object_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((object_size - 1) & object_size) {    /* not a power of 2? */
 | 
					        if ((object_size - 1) & object_size) {    /* not a power of 2? */
 | 
				
			||||||
            return -EINVAL;
 | 
					            return -EINVAL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1999,57 +2025,55 @@ static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
 | 
					static int sd_co_create(BlockdevCreateOptions *options, Error **errp)
 | 
				
			||||||
                                          Error **errp)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Error *err = NULL;
 | 
					    BlockdevCreateOptionsSheepdog *opts = &options->u.sheepdog;
 | 
				
			||||||
    int ret = 0;
 | 
					    int ret = 0;
 | 
				
			||||||
    uint32_t vid = 0;
 | 
					    uint32_t vid = 0;
 | 
				
			||||||
    char *backing_file = NULL;
 | 
					    char *backing_file = NULL;
 | 
				
			||||||
    char *buf = NULL;
 | 
					    char *buf = NULL;
 | 
				
			||||||
    BDRVSheepdogState *s;
 | 
					    BDRVSheepdogState *s;
 | 
				
			||||||
    SheepdogConfig cfg;
 | 
					 | 
				
			||||||
    uint64_t max_vdi_size;
 | 
					    uint64_t max_vdi_size;
 | 
				
			||||||
    bool prealloc = false;
 | 
					    bool prealloc = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(options->driver == BLOCKDEV_DRIVER_SHEEPDOG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = g_new0(BDRVSheepdogState, 1);
 | 
					    s = g_new0(BDRVSheepdogState, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (strstr(filename, "://")) {
 | 
					    /* Steal SocketAddress from QAPI, set NULL to prevent double free */
 | 
				
			||||||
        sd_parse_uri(&cfg, filename, &err);
 | 
					    s->addr = opts->location->server;
 | 
				
			||||||
    } else {
 | 
					    opts->location->server = NULL;
 | 
				
			||||||
        parse_vdiname(&cfg, filename, &err);
 | 
					
 | 
				
			||||||
    }
 | 
					    if (strlen(opts->location->vdi) >= sizeof(s->name)) {
 | 
				
			||||||
    if (err) {
 | 
					        error_setg(errp, "'vdi' string too long");
 | 
				
			||||||
        error_propagate(errp, err);
 | 
					        ret = -EINVAL;
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    pstrcpy(s->name, sizeof(s->name), opts->location->vdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    buf = cfg.port ? g_strdup_printf("%d", cfg.port) : NULL;
 | 
					    s->inode.vdi_size = opts->size;
 | 
				
			||||||
    s->addr = sd_socket_address(cfg.path, cfg.host, buf);
 | 
					    backing_file = opts->backing_file;
 | 
				
			||||||
    g_free(buf);
 | 
					 | 
				
			||||||
    strcpy(s->name, cfg.vdi);
 | 
					 | 
				
			||||||
    sd_config_done(&cfg);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->inode.vdi_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
 | 
					    if (!opts->has_preallocation) {
 | 
				
			||||||
                                 BDRV_SECTOR_SIZE);
 | 
					        opts->preallocation = PREALLOC_MODE_OFF;
 | 
				
			||||||
    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
 | 
					    }
 | 
				
			||||||
    buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
 | 
					    switch (opts->preallocation) {
 | 
				
			||||||
    if (!buf || !strcmp(buf, "off")) {
 | 
					    case PREALLOC_MODE_OFF:
 | 
				
			||||||
        prealloc = false;
 | 
					        prealloc = false;
 | 
				
			||||||
    } else if (!strcmp(buf, "full")) {
 | 
					        break;
 | 
				
			||||||
 | 
					    case PREALLOC_MODE_FULL:
 | 
				
			||||||
        prealloc = true;
 | 
					        prealloc = true;
 | 
				
			||||||
    } else {
 | 
					        break;
 | 
				
			||||||
        error_setg(errp, "Invalid preallocation mode: '%s'", buf);
 | 
					    default:
 | 
				
			||||||
 | 
					        error_setg(errp, "Preallocation mode not supported for Sheepdog");
 | 
				
			||||||
        ret = -EINVAL;
 | 
					        ret = -EINVAL;
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_free(buf);
 | 
					    if (opts->has_redundancy) {
 | 
				
			||||||
    buf = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
 | 
					        ret = parse_redundancy(s, opts->redundancy);
 | 
				
			||||||
    if (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");
 | 
				
			||||||
            goto out;
 | 
					            goto out;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -2061,20 +2085,20 @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
 | 
				
			|||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (backing_file) {
 | 
					    if (opts->has_backing_file) {
 | 
				
			||||||
        BlockBackend *blk;
 | 
					        BlockBackend *blk;
 | 
				
			||||||
        BDRVSheepdogState *base;
 | 
					        BDRVSheepdogState *base;
 | 
				
			||||||
        BlockDriver *drv;
 | 
					        BlockDriver *drv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Currently, only Sheepdog backing image is supported. */
 | 
					        /* Currently, only Sheepdog backing image is supported. */
 | 
				
			||||||
        drv = bdrv_find_protocol(backing_file, true, NULL);
 | 
					        drv = bdrv_find_protocol(opts->backing_file, true, NULL);
 | 
				
			||||||
        if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
 | 
					        if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
 | 
				
			||||||
            error_setg(errp, "backing_file must be a sheepdog image");
 | 
					            error_setg(errp, "backing_file must be a sheepdog image");
 | 
				
			||||||
            ret = -EINVAL;
 | 
					            ret = -EINVAL;
 | 
				
			||||||
            goto out;
 | 
					            goto out;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        blk = blk_new_open(backing_file, NULL, NULL,
 | 
					        blk = blk_new_open(opts->backing_file, NULL, NULL,
 | 
				
			||||||
                           BDRV_O_PROTOCOL, errp);
 | 
					                           BDRV_O_PROTOCOL, errp);
 | 
				
			||||||
        if (blk == NULL) {
 | 
					        if (blk == NULL) {
 | 
				
			||||||
            ret = -EIO;
 | 
					            ret = -EIO;
 | 
				
			||||||
@ -2142,28 +2166,96 @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (prealloc) {
 | 
					    if (prealloc) {
 | 
				
			||||||
        BlockDriverState *bs;
 | 
					        ret = sd_create_prealloc(opts->location, opts->size, errp);
 | 
				
			||||||
        QDict *opts;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        opts = qdict_new();
 | 
					 | 
				
			||||||
        qdict_put_str(opts, "driver", "sheepdog");
 | 
					 | 
				
			||||||
        bs = bdrv_open(filename, NULL, opts, BDRV_O_PROTOCOL | BDRV_O_RDWR,
 | 
					 | 
				
			||||||
                       errp);
 | 
					 | 
				
			||||||
        if (!bs) {
 | 
					 | 
				
			||||||
            goto out;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ret = sd_prealloc(bs, 0, s->inode.vdi_size, errp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bdrv_unref(bs);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    g_free(backing_file);
 | 
					    g_free(backing_file);
 | 
				
			||||||
    g_free(buf);
 | 
					    g_free(buf);
 | 
				
			||||||
 | 
					    g_free(s->addr);
 | 
				
			||||||
    g_free(s);
 | 
					    g_free(s);
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
 | 
				
			||||||
 | 
					                                          Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BlockdevCreateOptions *create_options = NULL;
 | 
				
			||||||
 | 
					    QDict *qdict, *location_qdict;
 | 
				
			||||||
 | 
					    QObject *crumpled;
 | 
				
			||||||
 | 
					    Visitor *v;
 | 
				
			||||||
 | 
					    const char *redundancy;
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    redundancy = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qdict = qemu_opts_to_qdict(opts, NULL);
 | 
				
			||||||
 | 
					    qdict_put_str(qdict, "driver", "sheepdog");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    location_qdict = qdict_new();
 | 
				
			||||||
 | 
					    qdict_put(qdict, "location", location_qdict);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sd_parse_filename(filename, location_qdict, &local_err);
 | 
				
			||||||
 | 
					    if (local_err) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qdict_flatten(qdict);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Change legacy command line options into QMP ones */
 | 
				
			||||||
 | 
					    static const QDictRenames opt_renames[] = {
 | 
				
			||||||
 | 
					        { BLOCK_OPT_BACKING_FILE,       "backing-file" },
 | 
				
			||||||
 | 
					        { BLOCK_OPT_OBJECT_SIZE,        "object-size" },
 | 
				
			||||||
 | 
					        { NULL, NULL },
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!qdict_rename_keys(qdict, opt_renames, errp)) {
 | 
				
			||||||
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Get the QAPI object */
 | 
				
			||||||
 | 
					    crumpled = qdict_crumple(qdict, errp);
 | 
				
			||||||
 | 
					    if (crumpled == NULL) {
 | 
				
			||||||
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    v = qobject_input_visitor_new_keyval(crumpled);
 | 
				
			||||||
 | 
					    visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err);
 | 
				
			||||||
 | 
					    visit_free(v);
 | 
				
			||||||
 | 
					    qobject_decref(crumpled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (local_err) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(create_options->driver == BLOCKDEV_DRIVER_SHEEPDOG);
 | 
				
			||||||
 | 
					    create_options->u.sheepdog.size =
 | 
				
			||||||
 | 
					        ROUND_UP(create_options->u.sheepdog.size, BDRV_SECTOR_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (redundancy) {
 | 
				
			||||||
 | 
					        create_options->u.sheepdog.has_redundancy = true;
 | 
				
			||||||
 | 
					        create_options->u.sheepdog.redundancy =
 | 
				
			||||||
 | 
					            parse_redundancy_str(redundancy);
 | 
				
			||||||
 | 
					        if (create_options->u.sheepdog.redundancy == NULL) {
 | 
				
			||||||
 | 
					            error_setg(errp, "Invalid redundancy mode");
 | 
				
			||||||
 | 
					            ret = -EINVAL;
 | 
				
			||||||
 | 
					            goto fail;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = sd_co_create(create_options, errp);
 | 
				
			||||||
 | 
					fail:
 | 
				
			||||||
 | 
					    qapi_free_BlockdevCreateOptions(create_options);
 | 
				
			||||||
 | 
					    QDECREF(qdict);
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sd_close(BlockDriverState *bs)
 | 
					static void sd_close(BlockDriverState *bs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Error *local_err = NULL;
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
@ -3143,6 +3235,7 @@ static BlockDriver bdrv_sheepdog = {
 | 
				
			|||||||
    .bdrv_reopen_commit           = sd_reopen_commit,
 | 
					    .bdrv_reopen_commit           = sd_reopen_commit,
 | 
				
			||||||
    .bdrv_reopen_abort            = sd_reopen_abort,
 | 
					    .bdrv_reopen_abort            = sd_reopen_abort,
 | 
				
			||||||
    .bdrv_close                   = sd_close,
 | 
					    .bdrv_close                   = sd_close,
 | 
				
			||||||
 | 
					    .bdrv_co_create               = sd_co_create,
 | 
				
			||||||
    .bdrv_co_create_opts          = sd_co_create_opts,
 | 
					    .bdrv_co_create_opts          = sd_co_create_opts,
 | 
				
			||||||
    .bdrv_has_zero_init           = bdrv_has_zero_init_1,
 | 
					    .bdrv_has_zero_init           = bdrv_has_zero_init_1,
 | 
				
			||||||
    .bdrv_getlength               = sd_getlength,
 | 
					    .bdrv_getlength               = sd_getlength,
 | 
				
			||||||
@ -3179,6 +3272,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
 | 
				
			|||||||
    .bdrv_reopen_commit           = sd_reopen_commit,
 | 
					    .bdrv_reopen_commit           = sd_reopen_commit,
 | 
				
			||||||
    .bdrv_reopen_abort            = sd_reopen_abort,
 | 
					    .bdrv_reopen_abort            = sd_reopen_abort,
 | 
				
			||||||
    .bdrv_close                   = sd_close,
 | 
					    .bdrv_close                   = sd_close,
 | 
				
			||||||
 | 
					    .bdrv_co_create               = sd_co_create,
 | 
				
			||||||
    .bdrv_co_create_opts          = sd_co_create_opts,
 | 
					    .bdrv_co_create_opts          = sd_co_create_opts,
 | 
				
			||||||
    .bdrv_has_zero_init           = bdrv_has_zero_init_1,
 | 
					    .bdrv_has_zero_init           = bdrv_has_zero_init_1,
 | 
				
			||||||
    .bdrv_getlength               = sd_getlength,
 | 
					    .bdrv_getlength               = sd_getlength,
 | 
				
			||||||
@ -3215,6 +3309,7 @@ static BlockDriver bdrv_sheepdog_unix = {
 | 
				
			|||||||
    .bdrv_reopen_commit           = sd_reopen_commit,
 | 
					    .bdrv_reopen_commit           = sd_reopen_commit,
 | 
				
			||||||
    .bdrv_reopen_abort            = sd_reopen_abort,
 | 
					    .bdrv_reopen_abort            = sd_reopen_abort,
 | 
				
			||||||
    .bdrv_close                   = sd_close,
 | 
					    .bdrv_close                   = sd_close,
 | 
				
			||||||
 | 
					    .bdrv_co_create               = sd_co_create,
 | 
				
			||||||
    .bdrv_co_create_opts          = sd_co_create_opts,
 | 
					    .bdrv_co_create_opts          = sd_co_create_opts,
 | 
				
			||||||
    .bdrv_has_zero_init           = bdrv_has_zero_init_1,
 | 
					    .bdrv_has_zero_init           = bdrv_has_zero_init_1,
 | 
				
			||||||
    .bdrv_getlength               = sd_getlength,
 | 
					    .bdrv_getlength               = sd_getlength,
 | 
				
			||||||
 | 
				
			|||||||
@ -3511,6 +3511,28 @@
 | 
				
			|||||||
  'data': { 'full': 'SheepdogRedundancyFull',
 | 
					  'data': { 'full': 'SheepdogRedundancyFull',
 | 
				
			||||||
            'erasure-coded': 'SheepdogRedundancyErasureCoded' } }
 | 
					            'erasure-coded': 'SheepdogRedundancyErasureCoded' } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					# @BlockdevCreateOptionsSheepdog:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Driver specific image creation options for Sheepdog.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# @location         Where to store the new image file
 | 
				
			||||||
 | 
					# @size             Size of the virtual disk in bytes
 | 
				
			||||||
 | 
					# @backing-file     File name of a base image
 | 
				
			||||||
 | 
					# @preallocation    Preallocation mode (allowed values: off, full)
 | 
				
			||||||
 | 
					# @redundancy       Redundancy of the image
 | 
				
			||||||
 | 
					# @object-size      Object size of the image
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Since: 2.12
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					{ 'struct': 'BlockdevCreateOptionsSheepdog',
 | 
				
			||||||
 | 
					  'data': { 'location':         'BlockdevOptionsSheepdog',
 | 
				
			||||||
 | 
					            'size':             'size',
 | 
				
			||||||
 | 
					            '*backing-file':    'str',
 | 
				
			||||||
 | 
					            '*preallocation':   'PreallocMode',
 | 
				
			||||||
 | 
					            '*redundancy':      'SheepdogRedundancy',
 | 
				
			||||||
 | 
					            '*object-size':     'size' } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# @BlockdevCreateNotSupported:
 | 
					# @BlockdevCreateNotSupported:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@ -3562,7 +3584,7 @@
 | 
				
			|||||||
      'raw':            'BlockdevCreateNotSupported',
 | 
					      'raw':            'BlockdevCreateNotSupported',
 | 
				
			||||||
      'rbd':            'BlockdevCreateOptionsRbd',
 | 
					      'rbd':            'BlockdevCreateOptionsRbd',
 | 
				
			||||||
      'replication':    'BlockdevCreateNotSupported',
 | 
					      'replication':    'BlockdevCreateNotSupported',
 | 
				
			||||||
      'sheepdog':       'BlockdevCreateNotSupported',
 | 
					      'sheepdog':       'BlockdevCreateOptionsSheepdog',
 | 
				
			||||||
      'ssh':            'BlockdevCreateNotSupported',
 | 
					      'ssh':            'BlockdevCreateNotSupported',
 | 
				
			||||||
      'throttle':       'BlockdevCreateNotSupported',
 | 
					      'throttle':       'BlockdevCreateNotSupported',
 | 
				
			||||||
      'vdi':            'BlockdevCreateNotSupported',
 | 
					      'vdi':            'BlockdevCreateNotSupported',
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user