block: Error parameter for create functions
Add an Error ** parameter to bdrv_create and its associated functions to allow more specific error messages. Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
		
							parent
							
								
									34b5d2c68e
								
							
						
					
					
						commit
						cc84d90ff5
					
				
							
								
								
									
										80
									
								
								block.c
								
								
								
								
							
							
						
						
									
										80
									
								
								block.c
								
								
								
								
							| 
						 | 
					@ -394,18 +394,26 @@ typedef struct CreateCo {
 | 
				
			||||||
    char *filename;
 | 
					    char *filename;
 | 
				
			||||||
    QEMUOptionParameter *options;
 | 
					    QEMUOptionParameter *options;
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					    Error *err;
 | 
				
			||||||
} CreateCo;
 | 
					} CreateCo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void coroutine_fn bdrv_create_co_entry(void *opaque)
 | 
					static void coroutine_fn bdrv_create_co_entry(void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CreateCo *cco = opaque;
 | 
					    CreateCo *cco = opaque;
 | 
				
			||||||
    assert(cco->drv);
 | 
					    assert(cco->drv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cco->ret = cco->drv->bdrv_create(cco->filename, cco->options, NULL);
 | 
					    ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
 | 
				
			||||||
 | 
					    if (error_is_set(&local_err)) {
 | 
				
			||||||
 | 
					        error_propagate(&cco->err, local_err);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    cco->ret = ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int bdrv_create(BlockDriver *drv, const char* filename,
 | 
					int bdrv_create(BlockDriver *drv, const char* filename,
 | 
				
			||||||
    QEMUOptionParameter *options)
 | 
					    QEMUOptionParameter *options, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -415,9 +423,11 @@ int bdrv_create(BlockDriver *drv, const char* filename,
 | 
				
			||||||
        .filename = g_strdup(filename),
 | 
					        .filename = g_strdup(filename),
 | 
				
			||||||
        .options = options,
 | 
					        .options = options,
 | 
				
			||||||
        .ret = NOT_DONE,
 | 
					        .ret = NOT_DONE,
 | 
				
			||||||
 | 
					        .err = NULL,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!drv->bdrv_create) {
 | 
					    if (!drv->bdrv_create) {
 | 
				
			||||||
 | 
					        error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
 | 
				
			||||||
        ret = -ENOTSUP;
 | 
					        ret = -ENOTSUP;
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -434,22 +444,37 @@ int bdrv_create(BlockDriver *drv, const char* filename,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = cco.ret;
 | 
					    ret = cco.ret;
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        if (error_is_set(&cco.err)) {
 | 
				
			||||||
 | 
					            error_propagate(errp, cco.err);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            error_setg_errno(errp, -ret, "Could not create image");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    g_free(cco.filename);
 | 
					    g_free(cco.filename);
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
 | 
					int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
 | 
				
			||||||
 | 
					                     Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BlockDriver *drv;
 | 
					    BlockDriver *drv;
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    drv = bdrv_find_protocol(filename, true);
 | 
					    drv = bdrv_find_protocol(filename, true);
 | 
				
			||||||
    if (drv == NULL) {
 | 
					    if (drv == NULL) {
 | 
				
			||||||
 | 
					        error_setg(errp, "Could not find protocol for file '%s'", filename);
 | 
				
			||||||
        return -ENOENT;
 | 
					        return -ENOENT;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return bdrv_create(drv, filename, options);
 | 
					    ret = bdrv_create(drv, filename, options, &local_err);
 | 
				
			||||||
 | 
					    if (error_is_set(&local_err)) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1082,11 +1107,14 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
 | 
				
			||||||
                drv->format_name);
 | 
					                drv->format_name);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options);
 | 
					        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
 | 
				
			||||||
        free_option_parameters(create_options);
 | 
					        free_option_parameters(create_options);
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
            error_setg_errno(errp, -ret, "Could not create temporary overlay "
 | 
					            error_setg_errno(errp, -ret, "Could not create temporary overlay "
 | 
				
			||||||
                             "'%s'", tmp_filename);
 | 
					                             "'%s': %s", tmp_filename,
 | 
				
			||||||
 | 
					                             error_get_pretty(local_err));
 | 
				
			||||||
 | 
					            error_free(local_err);
 | 
				
			||||||
 | 
					            local_err = NULL;
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4461,6 +4489,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
 | 
				
			||||||
    BlockDriverState *bs = NULL;
 | 
					    BlockDriverState *bs = NULL;
 | 
				
			||||||
    BlockDriver *drv, *proto_drv;
 | 
					    BlockDriver *drv, *proto_drv;
 | 
				
			||||||
    BlockDriver *backing_drv = NULL;
 | 
					    BlockDriver *backing_drv = NULL;
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
    int ret = 0;
 | 
					    int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Find driver and parse its options */
 | 
					    /* Find driver and parse its options */
 | 
				
			||||||
| 
						 | 
					@ -4547,10 +4576,13 @@ void bdrv_img_create(const char *filename, const char *fmt,
 | 
				
			||||||
            bs = bdrv_new("");
 | 
					            bs = bdrv_new("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
 | 
					            ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
 | 
				
			||||||
                            backing_drv, NULL);
 | 
					                            backing_drv, &local_err);
 | 
				
			||||||
            if (ret < 0) {
 | 
					            if (ret < 0) {
 | 
				
			||||||
                error_setg_errno(errp, -ret, "Could not open '%s'",
 | 
					                error_setg_errno(errp, -ret, "Could not open '%s': %s",
 | 
				
			||||||
                                 backing_file->value.s);
 | 
					                                 backing_file->value.s,
 | 
				
			||||||
 | 
					                                 error_get_pretty(local_err));
 | 
				
			||||||
 | 
					                error_free(local_err);
 | 
				
			||||||
 | 
					                local_err = NULL;
 | 
				
			||||||
                goto out;
 | 
					                goto out;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            bdrv_get_geometry(bs, &size);
 | 
					            bdrv_get_geometry(bs, &size);
 | 
				
			||||||
| 
						 | 
					@ -4569,22 +4601,19 @@ void bdrv_img_create(const char *filename, const char *fmt,
 | 
				
			||||||
        print_option_parameters(param);
 | 
					        print_option_parameters(param);
 | 
				
			||||||
        puts("");
 | 
					        puts("");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ret = bdrv_create(drv, filename, param);
 | 
					    ret = bdrv_create(drv, filename, param, &local_err);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret == -EFBIG) {
 | 
				
			||||||
        if (ret == -ENOTSUP) {
 | 
					        /* This is generally a better message than whatever the driver would
 | 
				
			||||||
            error_setg(errp,"Formatting or formatting option not supported for "
 | 
					         * deliver (especially because of the cluster_size_hint), since that
 | 
				
			||||||
                            "file format '%s'", fmt);
 | 
					         * is most probably not much different from "image too large". */
 | 
				
			||||||
        } else if (ret == -EFBIG) {
 | 
					        const char *cluster_size_hint = "";
 | 
				
			||||||
            const char *cluster_size_hint = "";
 | 
					        if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
 | 
				
			||||||
            if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
 | 
					            cluster_size_hint = " (try using a larger cluster size)";
 | 
				
			||||||
                cluster_size_hint = " (try using a larger cluster size)";
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            error_setg(errp, "The image size is too large for file format '%s'%s",
 | 
					 | 
				
			||||||
                       fmt, cluster_size_hint);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            error_setg(errp, "%s: error while creating %s: %s", filename, fmt,
 | 
					 | 
				
			||||||
                       strerror(-ret));
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        error_setg(errp, "The image size is too large for file format '%s'"
 | 
				
			||||||
 | 
					                   "%s", fmt, cluster_size_hint);
 | 
				
			||||||
 | 
					        error_free(local_err);
 | 
				
			||||||
 | 
					        local_err = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
| 
						 | 
					@ -4594,6 +4623,9 @@ out:
 | 
				
			||||||
    if (bs) {
 | 
					    if (bs) {
 | 
				
			||||||
        bdrv_unref(bs);
 | 
					        bdrv_unref(bs);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (error_is_set(&local_err)) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
 | 
					AioContext *bdrv_get_aio_context(BlockDriverState *bs)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -316,8 +316,10 @@ static int cow_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			||||||
        options++;
 | 
					        options++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = bdrv_create_file(filename, options);
 | 
					    ret = bdrv_create_file(filename, options, &local_err);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        qerror_report_err(local_err);
 | 
				
			||||||
 | 
					        error_free(local_err);
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -684,8 +684,10 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			||||||
        options++;
 | 
					        options++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = bdrv_create_file(filename, options);
 | 
					    ret = bdrv_create_file(filename, options, &local_err);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        qerror_report_err(local_err);
 | 
				
			||||||
 | 
					        error_free(local_err);
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1365,7 +1365,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
 | 
				
			||||||
    uint8_t* refcount_table;
 | 
					    uint8_t* refcount_table;
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = bdrv_create_file(filename, options);
 | 
					    ret = bdrv_create_file(filename, options, NULL);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -555,8 +555,10 @@ static int qed_create(const char *filename, uint32_t cluster_size,
 | 
				
			||||||
    int ret = 0;
 | 
					    int ret = 0;
 | 
				
			||||||
    BlockDriverState *bs = NULL;
 | 
					    BlockDriverState *bs = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = bdrv_create_file(filename, NULL);
 | 
					    ret = bdrv_create_file(filename, NULL, &local_err);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        qerror_report_err(local_err);
 | 
				
			||||||
 | 
					        error_free(local_err);
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,7 +133,15 @@ static int raw_has_zero_init(BlockDriverState *bs)
 | 
				
			||||||
static int raw_create(const char *filename, QEMUOptionParameter *options,
 | 
					static int raw_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			||||||
                      Error **errp)
 | 
					                      Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return bdrv_create_file(filename, options);
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = bdrv_create_file(filename, options, &local_err);
 | 
				
			||||||
 | 
					    if (error_is_set(&local_err)) {
 | 
				
			||||||
 | 
					        qerror_report_err(local_err);
 | 
				
			||||||
 | 
					        error_free(local_err);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int raw_open(BlockDriverState *bs, QDict *options, int flags,
 | 
					static int raw_open(BlockDriverState *bs, QDict *options, int flags,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2928,8 +2928,10 @@ static int enable_write_target(BDRVVVFATState *s)
 | 
				
			||||||
    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
 | 
					    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
 | 
				
			||||||
    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
 | 
					    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = bdrv_create(bdrv_qcow, s->qcow_filename, options);
 | 
					    ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, &local_err);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        qerror_report_err(local_err);
 | 
				
			||||||
 | 
					        error_free(local_err);
 | 
				
			||||||
        goto err;
 | 
					        goto err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,8 +142,9 @@ BlockDriver *bdrv_find_format(const char *format_name);
 | 
				
			||||||
BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
 | 
					BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
 | 
				
			||||||
                                          bool readonly);
 | 
					                                          bool readonly);
 | 
				
			||||||
int bdrv_create(BlockDriver *drv, const char* filename,
 | 
					int bdrv_create(BlockDriver *drv, const char* filename,
 | 
				
			||||||
    QEMUOptionParameter *options);
 | 
					    QEMUOptionParameter *options, Error **errp);
 | 
				
			||||||
int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
 | 
					int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
 | 
				
			||||||
 | 
					                     Error **errp);
 | 
				
			||||||
BlockDriverState *bdrv_new(const char *device_name);
 | 
					BlockDriverState *bdrv_new(const char *device_name);
 | 
				
			||||||
void bdrv_make_anon(BlockDriverState *bs);
 | 
					void bdrv_make_anon(BlockDriverState *bs);
 | 
				
			||||||
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
 | 
					void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								qemu-img.c
								
								
								
								
							
							
						
						
									
										16
									
								
								qemu-img.c
								
								
								
								
							| 
						 | 
					@ -1139,6 +1139,7 @@ static int img_convert(int argc, char **argv)
 | 
				
			||||||
    float local_progress = 0;
 | 
					    float local_progress = 0;
 | 
				
			||||||
    int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
 | 
					    int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
 | 
				
			||||||
    bool quiet = false;
 | 
					    bool quiet = false;
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fmt = NULL;
 | 
					    fmt = NULL;
 | 
				
			||||||
    out_fmt = "raw";
 | 
					    out_fmt = "raw";
 | 
				
			||||||
| 
						 | 
					@ -1341,18 +1342,11 @@ static int img_convert(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!skip_create) {
 | 
					    if (!skip_create) {
 | 
				
			||||||
        /* Create the new image */
 | 
					        /* Create the new image */
 | 
				
			||||||
        ret = bdrv_create(drv, out_filename, param);
 | 
					        ret = bdrv_create(drv, out_filename, param, &local_err);
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
            if (ret == -ENOTSUP) {
 | 
					            error_report("%s: error while converting %s: %s",
 | 
				
			||||||
                error_report("Formatting not supported for file format '%s'",
 | 
					                         out_filename, out_fmt, error_get_pretty(local_err));
 | 
				
			||||||
                             out_fmt);
 | 
					            error_free(local_err);
 | 
				
			||||||
            } else if (ret == -EFBIG) {
 | 
					 | 
				
			||||||
                error_report("The image size is too large for file format '%s'",
 | 
					 | 
				
			||||||
                             out_fmt);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                error_report("%s: error while converting %s: %s",
 | 
					 | 
				
			||||||
                             out_filename, out_fmt, strerror(-ret));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            goto out;
 | 
					            goto out;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue