nfs: Support .bdrv_co_create
This adds the .bdrv_co_create driver callback to nfs, 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
c22a034545
commit
a1a42af422
76
block/nfs.c
76
block/nfs.c
@ -551,33 +551,45 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options,
|
static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options,
|
||||||
int flags, int open_flags, Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockdevOptionsNfs *opts = NULL;
|
BlockdevOptionsNfs *opts = NULL;
|
||||||
QObject *crumpled = NULL;
|
QObject *crumpled = NULL;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int ret;
|
|
||||||
|
|
||||||
crumpled = qdict_crumple(options, errp);
|
crumpled = qdict_crumple(options, errp);
|
||||||
if (crumpled == NULL) {
|
if (crumpled == NULL) {
|
||||||
return -EINVAL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = qobject_input_visitor_new_keyval(crumpled);
|
v = qobject_input_visitor_new_keyval(crumpled);
|
||||||
visit_type_BlockdevOptionsNfs(v, NULL, &opts, &local_err);
|
visit_type_BlockdevOptionsNfs(v, NULL, &opts, &local_err);
|
||||||
visit_free(v);
|
visit_free(v);
|
||||||
|
qobject_decref(crumpled);
|
||||||
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options,
|
||||||
|
int flags, int open_flags, Error **errp)
|
||||||
|
{
|
||||||
|
BlockdevOptionsNfs *opts;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
opts = nfs_options_qdict_to_qapi(options, errp);
|
||||||
|
if (opts == NULL) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nfs_client_open(client, opts, flags, open_flags, errp);
|
ret = nfs_client_open(client, opts, flags, open_flags, errp);
|
||||||
fail:
|
fail:
|
||||||
qobject_decref(crumpled);
|
|
||||||
qapi_free_BlockdevOptionsNfs(opts);
|
qapi_free_BlockdevOptionsNfs(opts);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -614,18 +626,43 @@ static QemuOptsList nfs_create_opts = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
|
static int nfs_file_co_create(BlockdevCreateOptions *options, Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
int64_t ret, total_size;
|
BlockdevCreateOptionsNfs *opts = &options->u.nfs;
|
||||||
NFSClient *client = g_new0(NFSClient, 1);
|
NFSClient *client = g_new0(NFSClient, 1);
|
||||||
QDict *options = NULL;
|
int ret;
|
||||||
|
|
||||||
|
assert(options->driver == BLOCKDEV_DRIVER_NFS);
|
||||||
|
|
||||||
client->aio_context = qemu_get_aio_context();
|
client->aio_context = qemu_get_aio_context();
|
||||||
|
|
||||||
|
ret = nfs_client_open(client, opts->location, O_CREAT, 0, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = nfs_ftruncate(client->context, client->fh, opts->size);
|
||||||
|
nfs_client_close(client);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_free(client);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockdevCreateOptions *create_options;
|
||||||
|
BlockdevCreateOptionsNfs *nfs_opts;
|
||||||
|
QDict *options;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
create_options = g_new0(BlockdevCreateOptions, 1);
|
||||||
|
create_options->driver = BLOCKDEV_DRIVER_NFS;
|
||||||
|
nfs_opts = &create_options->u.nfs;
|
||||||
|
|
||||||
/* Read out options */
|
/* Read out options */
|
||||||
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
|
nfs_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
|
||||||
BDRV_SECTOR_SIZE);
|
BDRV_SECTOR_SIZE);
|
||||||
|
|
||||||
options = qdict_new();
|
options = qdict_new();
|
||||||
ret = nfs_parse_uri(url, options, errp);
|
ret = nfs_parse_uri(url, options, errp);
|
||||||
@ -633,15 +670,21 @@ static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nfs_client_open_qdict(client, options, O_CREAT, 0, errp);
|
nfs_opts->location = nfs_options_qdict_to_qapi(options, errp);
|
||||||
|
if (nfs_opts->location == NULL) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nfs_file_co_create(create_options, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = nfs_ftruncate(client->context, client->fh, total_size);
|
|
||||||
nfs_client_close(client);
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
QDECREF(options);
|
QDECREF(options);
|
||||||
g_free(client);
|
qapi_free_BlockdevCreateOptions(create_options);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -828,6 +871,7 @@ static BlockDriver bdrv_nfs = {
|
|||||||
|
|
||||||
.bdrv_file_open = nfs_file_open,
|
.bdrv_file_open = nfs_file_open,
|
||||||
.bdrv_close = nfs_file_close,
|
.bdrv_close = nfs_file_close,
|
||||||
|
.bdrv_co_create = nfs_file_co_create,
|
||||||
.bdrv_co_create_opts = nfs_file_co_create_opts,
|
.bdrv_co_create_opts = nfs_file_co_create_opts,
|
||||||
.bdrv_reopen_prepare = nfs_reopen_prepare,
|
.bdrv_reopen_prepare = nfs_reopen_prepare,
|
||||||
|
|
||||||
|
@ -3392,6 +3392,20 @@
|
|||||||
'size': 'size',
|
'size': 'size',
|
||||||
'*preallocation': 'PreallocMode' } }
|
'*preallocation': 'PreallocMode' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @BlockdevCreateOptionsNfs:
|
||||||
|
#
|
||||||
|
# Driver specific image creation options for NFS.
|
||||||
|
#
|
||||||
|
# @location Where to store the new image file
|
||||||
|
# @size Size of the virtual disk in bytes
|
||||||
|
#
|
||||||
|
# Since: 2.12
|
||||||
|
##
|
||||||
|
{ 'struct': 'BlockdevCreateOptionsNfs',
|
||||||
|
'data': { 'location': 'BlockdevOptionsNfs',
|
||||||
|
'size': 'size' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @BlockdevQcow2Version:
|
# @BlockdevQcow2Version:
|
||||||
#
|
#
|
||||||
@ -3491,7 +3505,7 @@
|
|||||||
'iscsi': 'BlockdevCreateNotSupported',
|
'iscsi': 'BlockdevCreateNotSupported',
|
||||||
'luks': 'BlockdevCreateNotSupported',
|
'luks': 'BlockdevCreateNotSupported',
|
||||||
'nbd': 'BlockdevCreateNotSupported',
|
'nbd': 'BlockdevCreateNotSupported',
|
||||||
'nfs': 'BlockdevCreateNotSupported',
|
'nfs': 'BlockdevCreateOptionsNfs',
|
||||||
'null-aio': 'BlockdevCreateNotSupported',
|
'null-aio': 'BlockdevCreateNotSupported',
|
||||||
'null-co': 'BlockdevCreateNotSupported',
|
'null-co': 'BlockdevCreateNotSupported',
|
||||||
'nvme': 'BlockdevCreateNotSupported',
|
'nvme': 'BlockdevCreateNotSupported',
|
||||||
|
Loading…
Reference in New Issue
Block a user