Commit 4534ff54 authored by Kevin Wolf's avatar Kevin Wolf
Browse files

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: default avatarKevin Wolf <>
parent dfc65f1f
......@@ -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);
......@@ -190,7 +190,12 @@ typedef struct BdrvCheckResult {
BlockFragInfo bfi;
} BdrvCheckResult;
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res);
typedef enum {
} BdrvCheckMode;
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
/* async block I/O */
typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector,
......@@ -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);
......@@ -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[] = {
......@@ -277,7 +277,8 @@ static void vdi_header_print(VdiHeader *header)
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;
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));
......@@ -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);
......@@ -10,9 +10,9 @@ STEXI
DEF("check", img_check,
"check [-f fmt] filename")
"check [-f fmt] [-r [leaks | all]] filename")
@item check [-f @var{fmt}] @var{filename}
@item check [-f @var{fmt}] [-r [leaks | all]] @var{filename}
DEF("create", img_create,
......@@ -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"
"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"
"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) {
......@@ -387,6 +395,17 @@ static int img_check(int argc, char **argv)
case 'f':
fmt = optarg;
case 'r':
flags |= BDRV_O_RDWR;
if (!strcmp(optarg, "leaks")) {
} else if (!strcmp(optarg, "all")) {
} else {
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");
......@@ -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.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment