aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c10
-rw-r--r--block.h10
-rw-r--r--qemu-img.c63
3 files changed, 64 insertions, 19 deletions
diff --git a/block.c b/block.c
index dd6dd76c6d..b0ceef0438 100644
--- a/block.c
+++ b/block.c
@@ -710,15 +710,19 @@ DeviceState *bdrv_get_attached(BlockDriverState *bs)
/*
* Run consistency checks on an image
*
- * Returns the number of errors or -errno when an internal error occurs
+ * Returns 0 if the check could be completed (it doesn't mean that the image is
+ * free of errors) or -errno when an internal error occured. The results of the
+ * check are stored in res.
*/
-int bdrv_check(BlockDriverState *bs)
+int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
{
if (bs->drv->bdrv_check == NULL) {
return -ENOTSUP;
}
- return bs->drv->bdrv_check(bs);
+ memset(res, 0, sizeof(*res));
+ res->corruptions = bs->drv->bdrv_check(bs);
+ return res->corruptions < 0 ? res->corruptions : 0;
}
/* commit COW file into the raw image */
diff --git a/block.h b/block.h
index 3d03b3e041..c2a7e4c762 100644
--- a/block.h
+++ b/block.h
@@ -74,7 +74,6 @@ void bdrv_close(BlockDriverState *bs);
int bdrv_attach(BlockDriverState *bs, DeviceState *qdev);
void bdrv_detach(BlockDriverState *bs, DeviceState *qdev);
DeviceState *bdrv_get_attached(BlockDriverState *bs);
-int bdrv_check(BlockDriverState *bs);
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
@@ -97,6 +96,15 @@ int bdrv_change_backing_file(BlockDriverState *bs,
const char *backing_file, const char *backing_fmt);
void bdrv_register(BlockDriver *bdrv);
+
+typedef struct BdrvCheckResult {
+ int corruptions;
+ int leaks;
+ int check_errors;
+} BdrvCheckResult;
+
+int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res);
+
/* async block I/O */
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
diff --git a/qemu-img.c b/qemu-img.c
index 700af21841..e300f911cb 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -425,11 +425,20 @@ out:
return 0;
}
+/*
+ * Checks an image for consistency. Exit codes:
+ *
+ * 0 - Check completed, image is good
+ * 1 - Check not completed because of internal errors
+ * 2 - Check completed, image is corrupted
+ * 3 - Check completed, image has leaked clusters, but is good otherwise
+ */
static int img_check(int argc, char **argv)
{
int c, ret;
const char *filename, *fmt;
BlockDriverState *bs;
+ BdrvCheckResult result;
fmt = NULL;
for(;;) {
@@ -453,28 +462,52 @@ static int img_check(int argc, char **argv)
if (!bs) {
return 1;
}
- ret = bdrv_check(bs);
- switch(ret) {
- case 0:
- printf("No errors were found on the image.\n");
- break;
- case -ENOTSUP:
+ ret = bdrv_check(bs, &result);
+
+ if (ret == -ENOTSUP) {
error("This image format does not support checks");
- break;
- default:
- if (ret < 0) {
- error("An error occurred during the check");
- } else {
- printf("%d errors were found on the image.\n", ret);
+ bdrv_delete(bs);
+ return 1;
+ }
+
+ if (!(result.corruptions || result.leaks || result.check_errors)) {
+ printf("No errors were found on the image.\n");
+ } else {
+ if (result.corruptions) {
+ printf("\n%d errors were found on the image.\n"
+ "Data may be corrupted, or further writes to the image "
+ "may corrupt it.\n",
+ result.corruptions);
+ }
+
+ if (result.leaks) {
+ printf("\n%d leaked clusters were found on the image.\n"
+ "This means waste of disk space, but no harm to data.\n",
+ result.leaks);
+ }
+
+ if (result.check_errors) {
+ printf("\n%d internal errors have occurred during the check.\n",
+ result.check_errors);
}
- break;
}
bdrv_delete(bs);
- if (ret) {
+
+ if (ret < 0 || result.check_errors) {
+ printf("\nAn error has occurred during the check: %s\n"
+ "The check is not complete and may have missed error.\n",
+ strerror(-ret));
return 1;
}
- return 0;
+
+ if (result.corruptions) {
+ return 2;
+ } else if (result.leaks) {
+ return 3;
+ } else {
+ return 0;
+ }
}
static int img_commit(int argc, char **argv)