From d3a78a02f2e87ef86eb6117969a5df52157391df Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <8a8dc925d6cdb62aba736eb1551195551e09271b.1366117835.git.minovotn@redhat.com> References: <8a8dc925d6cdb62aba736eb1551195551e09271b.1366117835.git.minovotn@redhat.com> From: Kevin Wolf Date: Thu, 7 Mar 2013 15:29:14 +0100 Subject: [PATCH 06/19] qemu-img check -r for repairing images RH-Author: Kevin Wolf Message-id: <1362670164-15796-3-git-send-email-kwolf@redhat.com> Patchwork-id: 49304 O-Subject: [RHEL-6.5 qemu-kvm PATCH 02/12] qemu-img check -r for repairing images Bugzilla: 888008 RH-Acked-by: Eric Blake RH-Acked-by: Miroslav Rezanina RH-Acked-by: Stefan Hajnoczi 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 (cherry picked from commit 4534ff5426afeeae5238ba10a696cafa9a0168ee) Conflicts: block/qed.c 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(-) Signed-off-by: Michal Novotny --- 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 1f75c37..a037192 100644 --- a/block.c +++ b/block.c @@ -1291,14 +1291,14 @@ bool bdrv_dev_is_medium_locked(BlockDriverState *bs) * free of errors) or -errno when an internal error occured. 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 33c135c..1ef82b6 100644 --- a/block.h +++ b/block.h @@ -214,7 +214,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 struct BlockDriverAIOCB BlockDriverAIOCB; diff --git a/block/qcow2.c b/block/qcow2.c index cd44d98..90faa5e 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1348,8 +1348,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 3d372a9..040d88e 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1533,11 +1533,12 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs, return ret; } -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 3450a2d..d4abfd3 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -291,7 +291,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; @@ -300,6 +301,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 3489a54..fb2a19f 100644 --- a/block_int.h +++ b/block_int.h @@ -205,7 +205,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 432777f..304d081 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -10,9 +10,9 @@ STEXI STEXI 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 c36a0ce..40afeff 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -91,6 +91,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 occurred.\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" @@ -395,10 +401,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; } @@ -410,6 +418,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) { @@ -417,11 +436,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) { bdrv_delete(bs); diff --git a/qemu-img.texi b/qemu-img.texi index 02ffdd0..20ac0eb 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. -- 1.7.11.7