Commit ab8bda76 authored by Kevin Wolf's avatar Kevin Wolf
Browse files

gluster: Support .bdrv_co_create



This adds the .bdrv_co_create driver callback to gluster, which enables
image creation over QMP.

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Reviewed-by: default avatarMax Reitz <mreitz@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
parent 3766ef57
Loading
Loading
Loading
Loading
+91 −44
Original line number Diff line number Diff line
@@ -655,7 +655,9 @@ out:
    return -errno;
}

static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
/* Converts options given in @filename and the @options QDict into the QAPI
 * object @gconf. */
static int qemu_gluster_parse(BlockdevOptionsGluster *gconf,
                              const char *filename,
                              QDict *options, Error **errp)
{
@@ -668,8 +670,7 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
                                    "[host[:port]]volume/path[?socket=...]"
                                    "[,file.debug=N]"
                                    "[,file.logfile=/path/filename.log]\n");
            errno = -ret;
            return NULL;
            return ret;
        }
    } else {
        ret = qemu_gluster_parse_json(gconf, options, errp);
@@ -685,10 +686,23 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
                             "file.server.1.transport=unix,"
                             "file.server.1.socket=/var/run/glusterd.socket ..."
                             "\n");
            errno = -ret;
            return NULL;
            return ret;
        }
    }

    return 0;
}

static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
                                      const char *filename,
                                      QDict *options, Error **errp)
{
    int ret;

    ret = qemu_gluster_parse(gconf, filename, options, errp);
    if (ret < 0) {
        errno = -ret;
        return NULL;
    }

    return qemu_gluster_glfs_init(gconf, errp);
@@ -1021,20 +1035,72 @@ static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
    return 0;
}

static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
                                                    QemuOpts *opts,
static int qemu_gluster_co_create(BlockdevCreateOptions *options,
                                  Error **errp)
{
    BlockdevOptionsGluster *gconf;
    BlockdevCreateOptionsGluster *opts = &options->u.gluster;
    struct glfs *glfs;
    struct glfs_fd *fd = NULL;
    int ret = 0;
    PreallocMode prealloc;
    int64_t total_size = 0;

    assert(options->driver == BLOCKDEV_DRIVER_GLUSTER);

    glfs = qemu_gluster_glfs_init(opts->location, errp);
    if (!glfs) {
        ret = -errno;
        goto out;
    }

    fd = glfs_creat(glfs, opts->location->path,
                    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
    if (!fd) {
        ret = -errno;
        goto out;
    }

    ret = qemu_gluster_do_truncate(fd, opts->size, opts->preallocation, errp);

out:
    if (fd) {
        if (glfs_close(fd) != 0 && ret == 0) {
            ret = -errno;
        }
    }
    glfs_clear_preopened(glfs);
    return ret;
}

static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
                                                    QemuOpts *opts,
                                                    Error **errp)
{
    BlockdevCreateOptions *options;
    BlockdevCreateOptionsGluster *gopts;
    BlockdevOptionsGluster *gconf;
    char *tmp = NULL;
    Error *local_err = NULL;
    int ret;

    options = g_new0(BlockdevCreateOptions, 1);
    options->driver = BLOCKDEV_DRIVER_GLUSTER;
    gopts = &options->u.gluster;

    gconf = g_new0(BlockdevOptionsGluster, 1);
    gopts->location = gconf;

    gopts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
                           BDRV_SECTOR_SIZE);

    tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
    gopts->preallocation = qapi_enum_parse(&PreallocMode_lookup, tmp,
                                           PREALLOC_MODE_OFF, &local_err);
    g_free(tmp);
    if (local_err) {
        error_propagate(errp, local_err);
        ret = -EINVAL;
        goto fail;
    }

    gconf->debug = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
                                           GLUSTER_DEBUG_DEFAULT);
    if (gconf->debug < 0) {
@@ -1050,42 +1116,19 @@ static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
    }
    gconf->has_logfile = true;

    glfs = qemu_gluster_init(gconf, filename, NULL, errp);
    if (!glfs) {
        ret = -errno;
        goto out;
    }

    total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
                          BDRV_SECTOR_SIZE);

    tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
    prealloc = qapi_enum_parse(&PreallocMode_lookup, tmp, PREALLOC_MODE_OFF,
                               &local_err);
    g_free(tmp);
    if (local_err) {
        error_propagate(errp, local_err);
        ret = -EINVAL;
        goto out;
    ret = qemu_gluster_parse(gconf, filename, NULL, errp);
    if (ret < 0) {
        goto fail;
    }

    fd = glfs_creat(glfs, gconf->path,
                    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
    if (!fd) {
        ret = -errno;
        goto out;
    ret = qemu_gluster_co_create(options, errp);
    if (ret < 0) {
        goto fail;
    }

    ret = qemu_gluster_do_truncate(fd, total_size, prealloc, errp);

out:
    if (fd) {
        if (glfs_close(fd) != 0 && ret == 0) {
            ret = -errno;
        }
    }
    qapi_free_BlockdevOptionsGluster(gconf);
    glfs_clear_preopened(glfs);
    ret = 0;
fail:
    qapi_free_BlockdevCreateOptions(options);
    return ret;
}

@@ -1436,6 +1479,7 @@ static BlockDriver bdrv_gluster = {
    .bdrv_reopen_commit           = qemu_gluster_reopen_commit,
    .bdrv_reopen_abort            = qemu_gluster_reopen_abort,
    .bdrv_close                   = qemu_gluster_close,
    .bdrv_co_create               = qemu_gluster_co_create,
    .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
    .bdrv_getlength               = qemu_gluster_getlength,
    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
@@ -1464,6 +1508,7 @@ static BlockDriver bdrv_gluster_tcp = {
    .bdrv_reopen_commit           = qemu_gluster_reopen_commit,
    .bdrv_reopen_abort            = qemu_gluster_reopen_abort,
    .bdrv_close                   = qemu_gluster_close,
    .bdrv_co_create               = qemu_gluster_co_create,
    .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
    .bdrv_getlength               = qemu_gluster_getlength,
    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
@@ -1492,6 +1537,7 @@ static BlockDriver bdrv_gluster_unix = {
    .bdrv_reopen_commit           = qemu_gluster_reopen_commit,
    .bdrv_reopen_abort            = qemu_gluster_reopen_abort,
    .bdrv_close                   = qemu_gluster_close,
    .bdrv_co_create               = qemu_gluster_co_create,
    .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
    .bdrv_getlength               = qemu_gluster_getlength,
    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
@@ -1526,6 +1572,7 @@ static BlockDriver bdrv_gluster_rdma = {
    .bdrv_reopen_commit           = qemu_gluster_reopen_commit,
    .bdrv_reopen_abort            = qemu_gluster_reopen_abort,
    .bdrv_close                   = qemu_gluster_close,
    .bdrv_co_create               = qemu_gluster_co_create,
    .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
    .bdrv_getlength               = qemu_gluster_getlength,
    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+17 −1
Original line number Diff line number Diff line
@@ -3376,6 +3376,22 @@
            '*preallocation':   'PreallocMode',
            '*nocow':           'bool' } }

##
# @BlockdevCreateOptionsGluster:
#
# Driver specific image creation options for gluster.
#
# @location         Where to store the new image file
# @size             Size of the virtual disk in bytes
# @preallocation    Preallocation mode for the new image (default: off)
#
# Since: 2.12
##
{ 'struct': 'BlockdevCreateOptionsGluster',
  'data': { 'location':         'BlockdevOptionsGluster',
            'size':             'size',
            '*preallocation':   'PreallocMode' } }

##
# @BlockdevQcow2Version:
#
@@ -3450,7 +3466,7 @@
      'file':           'BlockdevCreateOptionsFile',
      'ftp':            'BlockdevCreateNotSupported',
      'ftps':           'BlockdevCreateNotSupported',
      'gluster':        'BlockdevCreateNotSupported',
      'gluster':        'BlockdevCreateOptionsGluster',
      'host_cdrom':     'BlockdevCreateNotSupported',
      'host_device':    'BlockdevCreateNotSupported',
      'http':           'BlockdevCreateNotSupported',