Skip to content

Commit

Permalink
qemu-img check -r for repairing images
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
kevmw committed Jun 15, 2012
1 parent dfc65f1 commit 4534ff5
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 14 deletions.
4 changes: 2 additions & 2 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion block.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 6 additions & 1 deletion block/qcow2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
5 changes: 3 additions & 2 deletions block/qed.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand Down
7 changes: 6 additions & 1 deletion block/vdi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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));

Expand Down
3 changes: 2 additions & 1 deletion block_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions qemu-img-cmds.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
25 changes: 22 additions & 3 deletions qemu-img.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
Expand All @@ -387,18 +395,29 @@ 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) {
help();
}
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");
Expand Down
7 changes: 6 additions & 1 deletion qemu-img.texi
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down

0 comments on commit 4534ff5

Please sign in to comment.