diff mbox

[18/27] block/parallels: implement parallels_check method of block driver

Message ID 1425977481-13317-19-git-send-email-den@openvz.org
State New
Headers show

Commit Message

Denis V. Lunev March 10, 2015, 8:51 a.m. UTC
The check is very simple at the moment. It calculates necessary stats
and fix only the following errors:
- space leak at the end of the image. This would happens due to
  preallocation
- clusters outside the image are zeroed. Nothing else could be done here

Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Roman Kagan <rkagan@parallels.com>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/parallels.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

Comments

Roman Kagan March 10, 2015, 2:24 p.m. UTC | #1
On Tue, Mar 10, 2015 at 11:51:12AM +0300, Denis V. Lunev wrote:
> The check is very simple at the moment. It calculates necessary stats
> and fix only the following errors:
> - space leak at the end of the image. This would happens due to
>   preallocation
> - clusters outside the image are zeroed. Nothing else could be done here
> 
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Roman Kagan <rkagan@parallels.com>
> CC: Kevin Wolf <kwolf@redhat.com>
> CC: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  block/parallels.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 82 insertions(+)
> 
> diff --git a/block/parallels.c b/block/parallels.c
> index 65f6418..e5b475e 100644
> --- a/block/parallels.c
> +++ b/block/parallels.c
> @@ -228,6 +228,87 @@ fail:
>      return ret;
>  }
>  
> +
> +static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
> +                           BdrvCheckMode fix)
> +{
> +    BDRVParallelsState *s = bs->opaque;
> +    int64_t size, prev_off, high_off;
> +    int ret;
> +    uint32_t i;
> +    bool flush_bat = false;
> +    int cluster_size = s->tracks << BDRV_SECTOR_BITS;
> +
> +    size = bdrv_getlength(bs->file);
> +    if (size < 0) {
> +        res->check_errors++;
> +        return size;
> +    }
> +
> +    res->bfi.total_clusters = s->bat_size;
> +    res->bfi.compressed_clusters = 0; /* compression is not supported */
> +
> +    high_off = 0;
> +    prev_off = 0;
> +    for (i = 0; i < s->bat_size; i++) {
> +        int64_t off = bat2sect(s, i) << BDRV_SECTOR_BITS;
> +        if (off == 0)
> +            continue;

If you don't update prev_off here you can get fragmentation stats wrong
(dunno how important it is)

> +
> +        /* cluster outside the image */
> +        if (off > size) {
> +            fprintf(stderr, "%s cluster %u is outside image\n",
> +                    fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
> +            res->corruptions++;
> +            if (fix & BDRV_FIX_ERRORS) {
> +                s->bat_bitmap[i] = 0;
> +                res->corruptions_fixed++;
> +                flush_bat = true;
> +                continue;
> +            }

Ditto

Roman.
Denis V. Lunev March 10, 2015, 2:29 p.m. UTC | #2
On 10/03/15 17:24, Roman Kagan wrote:
> On Tue, Mar 10, 2015 at 11:51:12AM +0300, Denis V. Lunev wrote:
>> The check is very simple at the moment. It calculates necessary stats
>> and fix only the following errors:
>> - space leak at the end of the image. This would happens due to
>>    preallocation
>> - clusters outside the image are zeroed. Nothing else could be done here
>>
>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>> CC: Roman Kagan <rkagan@parallels.com>
>> CC: Kevin Wolf <kwolf@redhat.com>
>> CC: Stefan Hajnoczi <stefanha@redhat.com>
>> ---
>>   block/parallels.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 82 insertions(+)
>>
>> diff --git a/block/parallels.c b/block/parallels.c
>> index 65f6418..e5b475e 100644
>> --- a/block/parallels.c
>> +++ b/block/parallels.c
>> @@ -228,6 +228,87 @@ fail:
>>       return ret;
>>   }
>>   
>> +
>> +static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
>> +                           BdrvCheckMode fix)
>> +{
>> +    BDRVParallelsState *s = bs->opaque;
>> +    int64_t size, prev_off, high_off;
>> +    int ret;
>> +    uint32_t i;
>> +    bool flush_bat = false;
>> +    int cluster_size = s->tracks << BDRV_SECTOR_BITS;
>> +
>> +    size = bdrv_getlength(bs->file);
>> +    if (size < 0) {
>> +        res->check_errors++;
>> +        return size;
>> +    }
>> +
>> +    res->bfi.total_clusters = s->bat_size;
>> +    res->bfi.compressed_clusters = 0; /* compression is not supported */
>> +
>> +    high_off = 0;
>> +    prev_off = 0;
>> +    for (i = 0; i < s->bat_size; i++) {
>> +        int64_t off = bat2sect(s, i) << BDRV_SECTOR_BITS;
>> +        if (off == 0)
>> +            continue;
> If you don't update prev_off here you can get fragmentation stats wrong
> (dunno how important it is)

ok. by the way, I have missed braces here...

>> +
>> +        /* cluster outside the image */
>> +        if (off > size) {
>> +            fprintf(stderr, "%s cluster %u is outside image\n",
>> +                    fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
>> +            res->corruptions++;
>> +            if (fix & BDRV_FIX_ERRORS) {
>> +                s->bat_bitmap[i] = 0;
>> +                res->corruptions_fixed++;
>> +                flush_bat = true;
>> +                continue;
>> +            }
> Ditto
>
> Roman.
diff mbox

Patch

diff --git a/block/parallels.c b/block/parallels.c
index 65f6418..e5b475e 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -228,6 +228,87 @@  fail:
     return ret;
 }
 
+
+static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
+                           BdrvCheckMode fix)
+{
+    BDRVParallelsState *s = bs->opaque;
+    int64_t size, prev_off, high_off;
+    int ret;
+    uint32_t i;
+    bool flush_bat = false;
+    int cluster_size = s->tracks << BDRV_SECTOR_BITS;
+
+    size = bdrv_getlength(bs->file);
+    if (size < 0) {
+        res->check_errors++;
+        return size;
+    }
+
+    res->bfi.total_clusters = s->bat_size;
+    res->bfi.compressed_clusters = 0; /* compression is not supported */
+
+    high_off = 0;
+    prev_off = 0;
+    for (i = 0; i < s->bat_size; i++) {
+        int64_t off = bat2sect(s, i) << BDRV_SECTOR_BITS;
+        if (off == 0)
+            continue;
+
+        /* cluster outside the image */
+        if (off > size) {
+            fprintf(stderr, "%s cluster %u is outside image\n",
+                    fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
+            res->corruptions++;
+            if (fix & BDRV_FIX_ERRORS) {
+                s->bat_bitmap[i] = 0;
+                res->corruptions_fixed++;
+                flush_bat = true;
+                continue;
+            }
+        }
+
+        res->bfi.allocated_clusters++;
+        if (off > high_off) {
+            high_off = off;
+        }
+
+        if (prev_off != 0 && (prev_off + cluster_size) != off) {
+            res->bfi.fragmented_clusters++;
+        }
+        prev_off = off;
+    }
+
+    if (flush_bat) {
+        ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
+        if (ret < 0) {
+            res->check_errors++;
+            return ret;
+        }
+    }
+
+    res->image_end_offset = high_off + cluster_size;
+    if (size > res->image_end_offset) {
+        int64_t count;
+        count = DIV_ROUND_UP(size - res->image_end_offset, cluster_size);
+        fprintf(stderr, "%s space leaked at the end of the image %" PRId64 "\n",
+                fix & BDRV_FIX_LEAKS ? "Repairing" : "ERROR",
+                size - res->image_end_offset);
+        res->leaks += count;
+        if (fix & BDRV_FIX_LEAKS) {
+            ret = bdrv_truncate(bs->file, res->image_end_offset);
+            if (ret < 0) {
+                res->check_errors++;
+                return ret;
+            }
+            res->leaks_fixed += count;
+        }
+    }
+
+    return 0;
+}
+
+
 static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
 {
     int64_t total_size, cl_size;
@@ -429,6 +510,7 @@  static BlockDriver bdrv_parallels = {
     .bdrv_co_writev = parallels_co_writev,
 
     .bdrv_create    = parallels_create,
+    .bdrv_check     = parallels_check,
     .create_opts    = &parallels_create_opts,
 };