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:
Max Reitz 2013-09-06 17:14:26 +02:00 committed by Kevin Wolf
parent 34b5d2c68e
commit cc84d90ff5
9 changed files with 86 additions and 43 deletions

80
block.c
View File

@ -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)

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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,

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;
} }
} }