summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2010-06-29 11:43:13 +0200
committerKevin Wolf <kwolf@redhat.com>2010-07-06 17:05:48 +0200
commite076f3383b08a563d76c8beb9a716788a3987df9 (patch)
tree7c8fcc62f7f8e6ecef7baedffb7554de69e06ed2
parent734003e6153b3552b9406ef598a1e67aac4a899e (diff)
downloadqemu-e076f3383b08a563d76c8beb9a716788a3987df9.tar.gz
qemu-img check: Distinguish different kinds of errors
People think that their images are corrupted when in fact there are just some leaked clusters. Differentiating several error cases should make the messages more comprehensible. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-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)