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
					
				
							
								
								
									
										74
									
								
								block/nfs.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								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,17 +626,42 @@ 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();
 | 
				
			||||||
@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user