summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c4
-rw-r--r--block.h7
-rw-r--r--block/qcow2.c7
-rw-r--r--block/qed.c5
-rw-r--r--block/vdi.c7
-rw-r--r--block_int.h3
-rw-r--r--qemu-img-cmds.hx4
-rw-r--r--qemu-img.c25
-rw-r--r--qemu-img.texi7
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.