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 <kwolf@redhat.com>
master
Kevin Wolf 2012-05-11 16:07:02 +02:00
parent dfc65f1f78
commit 4534ff5426
9 changed files with 55 additions and 14 deletions

View File

@ -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

View File

@ -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,

View File

@ -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);
}

View File

@ -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[] = {

View File

@ -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));

View File

@ -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);

View File

@ -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,

View File

@ -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");

View File

@ -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.