Using the new 'bdrv_co_delete_file' interface, bdrv_delete_file can be used in a way similar of the existing bdrv_create_file to invoke a driver, given by a format @fmt, to clean up a created file.
The logic is also similar to what is already done in bdrv_create_file: a qemu_coroutine is created if needed, a specialized function bdrv_delete_co_entry is used to call the bdrv_co_delete_file co-routine of the driver, if the driver implements it. Suggested-by: Daniel P. Berrangé <berra...@redhat.com> Signed-off-by: Daniel Henrique Barboza <danielhb...@gmail.com> --- @Daniel: I put the 'Suggested-by' tag here aware that what is being done in this patch wasn't explicitly suggested by you in that review. However, since it's a consequence of your suggestion, here it is. If you mind the tag here, let me know and we can remove it. block.c | 72 +++++++++++++++++++++++++++++++++++++++++++ include/block/block.h | 3 ++ 2 files changed, 75 insertions(+) diff --git a/block.c b/block.c index 2b632baba2..5c7781e471 100644 --- a/block.c +++ b/block.c @@ -592,6 +592,78 @@ done: return ret; } +static void coroutine_fn bdrv_delete_co_entry(void *opaque) +{ + Error *local_err = NULL; + int ret; + + CreateCo *cco = opaque; + assert(cco->drv); + + ret = cco->drv->bdrv_co_delete_file(cco->filename, &local_err); + error_propagate(&cco->err, local_err); + cco->ret = ret; +} + +int bdrv_delete_file(const char *filename, const char *fmt, + Error **errp) +{ + + BlockDriver *drv = bdrv_find_format(fmt); + Coroutine *co; + CreateCo cco = { + .drv = drv, + .filename = g_strdup(filename), + .ret = NOT_DONE, + .err = NULL, + }; + int ret; + + if (!drv) { + error_setg(errp, "Unknown file format '%s'", fmt); + ret = -ENOENT; + goto out; + } + + if (!drv->bdrv_co_delete_file) { + error_setg(errp, "Driver '%s' does not support image delete", + drv->format_name); + ret = -ENOTSUP; + goto out; + } + + if (!drv->bdrv_co_delete_file) { + error_setg(errp, "Driver '%s' does not support image delete", + drv->format_name); + ret = -ENOTSUP; + goto out; + } + + if (qemu_in_coroutine()) { + /* Fast-path if already in coroutine context */ + bdrv_delete_co_entry(&cco); + } else { + co = qemu_coroutine_create(bdrv_delete_co_entry, &cco); + qemu_coroutine_enter(co); + while (cco.ret == NOT_DONE) { + aio_poll(qemu_get_aio_context(), true); + } + } + + ret = cco.ret; + if (ret < 0) { + if (cco.err) { + error_propagate(errp, cco.err); + } else { + error_setg_errno(errp, -ret, "Could not delete image"); + } + } + +out: + g_free(cco.filename); + return ret; +} + /** * Try to get @bs's logical and physical block size. * On success, store them in @bsz struct and return 0. diff --git a/include/block/block.h b/include/block/block.h index efb77daf9f..9b66cf00cb 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -366,6 +366,9 @@ void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base); bool bdrv_path_is_regular_file(const char *path); int coroutine_fn bdrv_co_delete_file_generic(const char *filename, Error **errp); +int bdrv_delete_file(const char *filename, const char *fmt, + Error **errp); + typedef struct BdrvCheckResult { int corruptions; -- 2.20.1