From 4534ff5426afeeae5238ba10a696cafa9a0168ee Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 11 May 2012 16:07:02 +0200 Subject: [PATCH] qemu-img check -r for repairing images The QED block driver already provides the functionality to not only detect inconsistencies in images, but also fix them. However, this functionality cannot be manually invoked with qemu-img, but the check happens only automatically during bdrv_open(). This adds a -r switch to qemu-img check that allows manual invocation of an image repair. Signed-off-by: Kevin Wolf --- block.c | 4 ++-- block.h | 7 ++++++- block/qcow2.c | 7 ++++++- block/qed.c | 5 +++-- block/vdi.c | 7 ++++++- block_int.h | 3 ++- qemu-img-cmds.hx | 4 ++-- qemu-img.c | 25 ++++++++++++++++++++++--- qemu-img.texi | 7 ++++++- 9 files changed, 55 insertions(+), 14 deletions(-) diff --git a/block.c b/block.c index c07ff390ce..355ac8618a 100644 --- a/block.c +++ b/block.c @@ -1222,14 +1222,14 @@ bool bdrv_dev_is_medium_locked(BlockDriverState *bs) * free of errors) or -errno when an internal error occurred. The results of the * check are stored in res. */ -int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res) +int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) { if (bs->drv->bdrv_check == NULL) { return -ENOTSUP; } memset(res, 0, sizeof(*res)); - return bs->drv->bdrv_check(bs, res); + return bs->drv->bdrv_check(bs, res, fix); } #define COMMIT_BUF_SECTORS 2048 diff --git a/block.h b/block.h index 799cf48cc2..61b7e8ecb9 100644 --- a/block.h +++ b/block.h @@ -190,7 +190,12 @@ typedef struct BdrvCheckResult { BlockFragInfo bfi; } BdrvCheckResult; -int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res); +typedef enum { + BDRV_FIX_LEAKS = 1, + BDRV_FIX_ERRORS = 2, +} BdrvCheckMode; + +int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); /* async block I/O */ typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector, diff --git a/block/qcow2.c b/block/qcow2.c index c2e49cded3..77970155ab 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1470,8 +1470,13 @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) } -static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result) +static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) { + if (fix) { + return -ENOTSUP; + } + return qcow2_check_refcounts(bs, result); } diff --git a/block/qed.c b/block/qed.c index 30a31f907f..ab5972466c 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1517,11 +1517,12 @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs) bdrv_qed_open(bs, bs->open_flags); } -static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result) +static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) { BDRVQEDState *s = bs->opaque; - return qed_check(s, result, false); + return qed_check(s, result, !!fix); } static QEMUOptionParameter qed_create_options[] = { diff --git a/block/vdi.c b/block/vdi.c index 119d3c74da..57325d65c4 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -277,7 +277,8 @@ static void vdi_header_print(VdiHeader *header) } #endif -static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res) +static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix) { /* TODO: additional checks possible. */ BDRVVdiState *s = (BDRVVdiState *)bs->opaque; @@ -286,6 +287,10 @@ static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res) uint32_t *bmap; logout("\n"); + if (fix) { + return -ENOTSUP; + } + bmap = g_malloc(s->header.blocks_in_image * sizeof(uint32_t)); memset(bmap, 0xff, s->header.blocks_in_image * sizeof(uint32_t)); diff --git a/block_int.h b/block_int.h index 3d4abc6575..1fb5352d0e 100644 --- a/block_int.h +++ b/block_int.h @@ -241,7 +241,8 @@ struct BlockDriver { * Returns 0 for completed check, -errno for internal errors. * The check results are stored in result. */ - int (*bdrv_check)(BlockDriverState* bs, BdrvCheckResult *result); + int (*bdrv_check)(BlockDriverState* bs, BdrvCheckResult *result, + BdrvCheckMode fix); void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event); diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 49dce7c928..39419a0314 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -10,9 +10,9 @@ STEXI ETEXI DEF("check", img_check, - "check [-f fmt] filename") + "check [-f fmt] [-r [leaks | all]] filename") STEXI -@item check [-f @var{fmt}] @var{filename} +@item check [-f @var{fmt}] [-r [leaks | all]] @var{filename} ETEXI DEF("create", img_create, diff --git a/qemu-img.c b/qemu-img.c index c8a70ffc93..c45ff62a28 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -85,6 +85,12 @@ static void help(void) " '-S' indicates the consecutive number of bytes that must contain only zeros\n" " for qemu-img to create a sparse image during conversion\n" "\n" + "Parameters to check subcommand:\n" + " '-r' tries to repair any inconsistencies that are found during the check.\n" + " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n" + " kinds of errors, with a higher risk of choosing the wrong fix or\n" + " hiding corruption that has already occured.\n" + "\n" "Parameters to snapshot subcommand:\n" " 'snapshot' is the name of the snapshot to create, apply or delete\n" " '-a' applies a snapshot (revert disk to saved state)\n" @@ -372,10 +378,12 @@ static int img_check(int argc, char **argv) const char *filename, *fmt; BlockDriverState *bs; BdrvCheckResult result; + int fix = 0; + int flags = BDRV_O_FLAGS; fmt = NULL; for(;;) { - c = getopt(argc, argv, "f:h"); + c = getopt(argc, argv, "f:hr:"); if (c == -1) { break; } @@ -387,6 +395,17 @@ static int img_check(int argc, char **argv) case 'f': fmt = optarg; break; + case 'r': + flags |= BDRV_O_RDWR; + + if (!strcmp(optarg, "leaks")) { + fix = BDRV_FIX_LEAKS; + } else if (!strcmp(optarg, "all")) { + fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS; + } else { + help(); + } + break; } } if (optind >= argc) { @@ -394,11 +413,11 @@ static int img_check(int argc, char **argv) } filename = argv[optind++]; - bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS); + bs = bdrv_new_open(filename, fmt, flags); if (!bs) { return 1; } - ret = bdrv_check(bs, &result); + ret = bdrv_check(bs, &result, fix); if (ret == -ENOTSUP) { error_report("This image format does not support checks"); diff --git a/qemu-img.texi b/qemu-img.texi index 6fc3c28e0d..5a7b2bb1f2 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -70,10 +70,15 @@ lists all snapshots in the given image Command description: @table @option -@item check [-f @var{fmt}] @var{filename} +@item check [-f @var{fmt}] [-r [leaks | all]] @var{filename} Perform a consistency check on the disk image @var{filename}. +If @code{-r} is specified, qemu-img tries to repair any inconsistencies found +during the check. @code{-r leaks} repairs only cluster leaks, whereas +@code{-r all} fixes all kinds of errors, with a higher risk of choosing the +wrong fix or hiding corruption that has already occured. + Only the formats @code{qcow2}, @code{qed} and @code{vdi} support consistency checks. -- 2.34.1