diff mbox

[v7,07/42] ram_debug_dump_bitmap: Dump a migration bitmap as text

Message ID 1434450415-11339-8-git-send-email-dgilbert@redhat.com
State New
Headers show

Commit Message

Dr. David Alan Gilbert June 16, 2015, 10:26 a.m. UTC
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Useful for debugging the migration bitmap and other bitmaps
of the same format (including the sentmap in postcopy).

The bitmap is printed to stderr.
Lines that are all the expected value are excluded so the output
can be quite compact for many bitmaps.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 include/migration/migration.h |  1 +
 migration/ram.c               | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

Comments

Juan Quintela June 17, 2015, 12:17 p.m. UTC | #1
"Dr. David Alan Gilbert (git)" <dgilbert@redhat.com> wrote:
> From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
>
> Useful for debugging the migration bitmap and other bitmaps
> of the same format (including the sentmap in postcopy).
>
> The bitmap is printed to stderr.
> Lines that are all the expected value are excluded so the output
> can be quite compact for many bitmaps.
>
> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
>  include/migration/migration.h |  1 +
>  migration/ram.c               | 38 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+)
>
> diff --git a/include/migration/migration.h b/include/migration/migration.h
> index 9387c8c..b3a7f75 100644
> --- a/include/migration/migration.h
> +++ b/include/migration/migration.h
> @@ -144,6 +144,7 @@ uint64_t xbzrle_mig_pages_cache_miss(void);
>  double xbzrle_mig_cache_miss_rate(void);
>  
>  void ram_handle_compressed(void *host, uint8_t ch, uint64_t size);
> +void ram_debug_dump_bitmap(unsigned long *todump, bool expected);
>  
>  /**
>   * @migrate_add_blocker - prevent migration from proceeding
> diff --git a/migration/ram.c b/migration/ram.c
> index 57368e1..efc215a 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -1051,6 +1051,44 @@ static void reset_ram_globals(void)
>  
>  #define MAX_WAIT 50 /* ms, half buffered_file limit */
>  
> +/*
> + * 'expected' is the value you expect the bitmap mostly to be full
> + * of; it won't bother printing lines that are all this value.
> + * If 'todump' is null the migration bitmap is dumped.
> + */
> +void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
> +{
> +    int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
> +
> +    int64_t cur;
> +    int64_t linelen = 128;
> +    char linebuf[129];
> +
> +    if (!todump) {
> +        todump = migration_bitmap;
> +    }

Why?  Just alssert that todump!= NULL?


> +
> +    for (cur = 0; cur < ram_pages; cur += linelen) {
> +        int64_t curb;
> +        bool found = false;
> +        /*
> +         * Last line; catch the case where the line length
> +         * is longer than remaining ram
> +         */
> +        if (cur + linelen > ram_pages) {
> +            linelen = ram_pages - cur;
> +        }
> +        for (curb = 0; curb < linelen; curb++) {
> +            bool thisbit = test_bit(cur + curb, todump);
> +            linebuf[curb] = thisbit ? '1' : '.';

Put 1 and 0?  Why the dot?

> +            found = found || (thisbit != expected);
> +        }
> +        if (found) {
> +            linebuf[curb] = '\0';
> +            fprintf(stderr,  "0x%08" PRIx64 " : %s\n", cur, linebuf);
> +        }
> +    }
> +}


And once here, why are we doing it this way?  We have

find_first_bit(addr, nbits) and find_first_zero_bit(addr, nbits) and
friends?

Doiwg the walk by hand looks weird, no?

Later, Juan.
Dr. David Alan Gilbert June 19, 2015, 5:04 p.m. UTC | #2
* Juan Quintela (quintela@redhat.com) wrote:
> "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com> wrote:
> > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> >
> > Useful for debugging the migration bitmap and other bitmaps
> > of the same format (including the sentmap in postcopy).
> >
> > The bitmap is printed to stderr.
> > Lines that are all the expected value are excluded so the output
> > can be quite compact for many bitmaps.
> >
> > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> > ---
> >  include/migration/migration.h |  1 +
> >  migration/ram.c               | 38 ++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 39 insertions(+)
> >
> > diff --git a/include/migration/migration.h b/include/migration/migration.h
> > index 9387c8c..b3a7f75 100644
> > --- a/include/migration/migration.h
> > +++ b/include/migration/migration.h
> > @@ -144,6 +144,7 @@ uint64_t xbzrle_mig_pages_cache_miss(void);
> >  double xbzrle_mig_cache_miss_rate(void);
> >  
> >  void ram_handle_compressed(void *host, uint8_t ch, uint64_t size);
> > +void ram_debug_dump_bitmap(unsigned long *todump, bool expected);
> >  
> >  /**
> >   * @migrate_add_blocker - prevent migration from proceeding
> > diff --git a/migration/ram.c b/migration/ram.c
> > index 57368e1..efc215a 100644
> > --- a/migration/ram.c
> > +++ b/migration/ram.c
> > @@ -1051,6 +1051,44 @@ static void reset_ram_globals(void)
> >  
> >  #define MAX_WAIT 50 /* ms, half buffered_file limit */
> >  
> > +/*
> > + * 'expected' is the value you expect the bitmap mostly to be full
> > + * of; it won't bother printing lines that are all this value.
> > + * If 'todump' is null the migration bitmap is dumped.
> > + */
> > +void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
> > +{
> > +    int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
> > +
> > +    int64_t cur;
> > +    int64_t linelen = 128;
> > +    char linebuf[129];
> > +
> > +    if (!todump) {
> > +        todump = migration_bitmap;
> > +    }
> 
> Why?  Just alssert that todump!= NULL?

'migration_bitmap' is static to ram.c, so allowing NULL to get
you a dump of the migration_bitmap means that if you call this
dump routine from any error path you're debugging anywhere in qemu
then you can dump the migration bitmap.  e.g. I was adding calls
to this in migration.c and migration/postcopy-ram.c in error
paths I was trying to debug.

> > +    for (cur = 0; cur < ram_pages; cur += linelen) {
> > +        int64_t curb;
> > +        bool found = false;
> > +        /*
> > +         * Last line; catch the case where the line length
> > +         * is longer than remaining ram
> > +         */
> > +        if (cur + linelen > ram_pages) {
> > +            linelen = ram_pages - cur;
> > +        }
> > +        for (curb = 0; curb < linelen; curb++) {
> > +            bool thisbit = test_bit(cur + curb, todump);
> > +            linebuf[curb] = thisbit ? '1' : '.';
> 
> Put 1 and 0?  Why the dot?

It's easier to see an occasional '1' in a big field of .'s.

> > +            found = found || (thisbit != expected);
> > +        }
> > +        if (found) {
> > +            linebuf[curb] = '\0';
> > +            fprintf(stderr,  "0x%08" PRIx64 " : %s\n", cur, linebuf);
> > +        }
> > +    }
> > +}
> 
> 
> And once here, why are we doing it this way?  We have
> 
> find_first_bit(addr, nbits) and find_first_zero_bit(addr, nbits) and
> friends?
> 
> Doiwg the walk by hand looks weird, no?

Here's a compile-tested-only version using find_  - it's bigger, if you think
it's better I can use this instead:

void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
{
    int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;

    int64_t cur;
    int64_t linelen = 128;

    if (!todump) {
        todump = migration_bitmap;
    }

    for (cur = 0; cur < ram_pages; cur += linelen) {
        int64_t curb;
        unsigned long next_bit;

        /*
         * Last line; catch the case where the line length
         * is longer than remaining ram
         */
        if (cur + linelen > ram_pages) {
            linelen = ram_pages - cur;
        }
        if (expected) {
            next_bit = find_next_bit(todump, cur + linelen, cur);
        } else {
            next_bit = find_next_zero_bit(todump, cur + linelen, cur);
        }
        if (next_bit >= (cur + linelen)) {
            continue;
        }

        for (curb = 0; curb < linelen; curb++) {
            bool thisbit = test_bit(cur + curb, todump);
            fputc(thisbit ? '1' : '.', stderr);
        }
        fputc('\n', stderr);
    }
}

Dave


> 
> Later, Juan.
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
Amit Shah July 13, 2015, 9:12 a.m. UTC | #3
On (Tue) 16 Jun 2015 [11:26:20], Dr. David Alan Gilbert (git) wrote:
> From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> 
> Useful for debugging the migration bitmap and other bitmaps
> of the same format (including the sentmap in postcopy).
> 
> The bitmap is printed to stderr.
> Lines that are all the expected value are excluded so the output
> can be quite compact for many bitmaps.
> 
> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

Reviewed-by: Amit Shah <amit.shah@redhat.com>

		Amit
Juan Quintela July 13, 2015, 10:15 a.m. UTC | #4
"Dr. David Alan Gilbert" <dgilbert@redhat.com> wrote:
> * Juan Quintela (quintela@redhat.com) wrote:
>> "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com> wrote:
>> > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
>> >
>> > Useful for debugging the migration bitmap and other bitmaps
>> > of the same format (including the sentmap in postcopy).
>> >
>> > The bitmap is printed to stderr.
>> > Lines that are all the expected value are excluded so the output
>> > can be quite compact for many bitmaps.
>> >
>> > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> > ---
>> >  include/migration/migration.h |  1 +
>> >  migration/ram.c               | 38 ++++++++++++++++++++++++++++++++++++++
>> >  2 files changed, 39 insertions(+)
>> >
>> > diff --git a/include/migration/migration.h b/include/migration/migration.h
>> > index 9387c8c..b3a7f75 100644
>> > --- a/include/migration/migration.h
>> > +++ b/include/migration/migration.h
>> > @@ -144,6 +144,7 @@ uint64_t xbzrle_mig_pages_cache_miss(void);
>> >  double xbzrle_mig_cache_miss_rate(void);
>> >  
>> >  void ram_handle_compressed(void *host, uint8_t ch, uint64_t size);
>> > +void ram_debug_dump_bitmap(unsigned long *todump, bool expected);
>> >  
>> >  /**
>> >   * @migrate_add_blocker - prevent migration from proceeding
>> > diff --git a/migration/ram.c b/migration/ram.c
>> > index 57368e1..efc215a 100644
>> > --- a/migration/ram.c
>> > +++ b/migration/ram.c
>> > @@ -1051,6 +1051,44 @@ static void reset_ram_globals(void)
>> >  
>> >  #define MAX_WAIT 50 /* ms, half buffered_file limit */
>> >  
>> > +/*
>> > + * 'expected' is the value you expect the bitmap mostly to be full
>> > + * of; it won't bother printing lines that are all this value.
>> > + * If 'todump' is null the migration bitmap is dumped.
>> > + */
>> > +void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
>> > +{
>> > +    int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
>> > +
>> > +    int64_t cur;
>> > +    int64_t linelen = 128;
>> > +    char linebuf[129];
>> > +
>> > +    if (!todump) {
>> > +        todump = migration_bitmap;
>> > +    }
>> 
>> Why?  Just alssert that todump!= NULL?
>
> 'migration_bitmap' is static to ram.c, so allowing NULL to get
> you a dump of the migration_bitmap means that if you call this
> dump routine from any error path you're debugging anywhere in qemu
> then you can dump the migration bitmap.  e.g. I was adding calls
> to this in migration.c and migration/postcopy-ram.c in error
> paths I was trying to debug.

ok.

>
>> > +    for (cur = 0; cur < ram_pages; cur += linelen) {
>> > +        int64_t curb;
>> > +        bool found = false;
>> > +        /*
>> > +         * Last line; catch the case where the line length
>> > +         * is longer than remaining ram
>> > +         */
>> > +        if (cur + linelen > ram_pages) {
>> > +            linelen = ram_pages - cur;
>> > +        }
>> > +        for (curb = 0; curb < linelen; curb++) {
>> > +            bool thisbit = test_bit(cur + curb, todump);
>> > +            linebuf[curb] = thisbit ? '1' : '.';
>> 
>> Put 1 and 0?  Why the dot?
>
> It's easier to see an occasional '1' in a big field of .'s.

ok.

>
>> > +            found = found || (thisbit != expected);
>> > +        }
>> > +        if (found) {
>> > +            linebuf[curb] = '\0';
>> > +            fprintf(stderr,  "0x%08" PRIx64 " : %s\n", cur, linebuf);
>> > +        }
>> > +    }
>> > +}
>> 
>> 
>> And once here, why are we doing it this way?  We have
>> 
>> find_first_bit(addr, nbits) and find_first_zero_bit(addr, nbits) and
>> friends?
>> 
>> Doiwg the walk by hand looks weird, no?
>
> Here's a compile-tested-only version using find_  - it's bigger, if you think
> it's better I can use this instead:
>
> void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
> {
>     int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
>
>     int64_t cur;
>     int64_t linelen = 128;
>
>     if (!todump) {
>         todump = migration_bitmap;
>     }
>
>     for (cur = 0; cur < ram_pages; cur += linelen) {
>         int64_t curb;
>         unsigned long next_bit;
>
>         /*
>          * Last line; catch the case where the line length
>          * is longer than remaining ram
>          */
>         if (cur + linelen > ram_pages) {
>             linelen = ram_pages - cur;
>         }
>         if (expected) {
>             next_bit = find_next_bit(todump, cur + linelen, cur);
>         } else {
>             next_bit = find_next_zero_bit(todump, cur + linelen, cur);
>         }
>         if (next_bit >= (cur + linelen)) {
>             continue;
>         }
>
>         for (curb = 0; curb < linelen; curb++) {
>             bool thisbit = test_bit(cur + curb, todump);
>             fputc(thisbit ? '1' : '.', stderr);
>         }
>         fputc('\n', stderr);
>     }
> }
>
> Dave

Reviewed-by: Juan Quintela <quintela@redhat.com>


>
>
>> 
>> Later, Juan.
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
diff mbox

Patch

diff --git a/include/migration/migration.h b/include/migration/migration.h
index 9387c8c..b3a7f75 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -144,6 +144,7 @@  uint64_t xbzrle_mig_pages_cache_miss(void);
 double xbzrle_mig_cache_miss_rate(void);
 
 void ram_handle_compressed(void *host, uint8_t ch, uint64_t size);
+void ram_debug_dump_bitmap(unsigned long *todump, bool expected);
 
 /**
  * @migrate_add_blocker - prevent migration from proceeding
diff --git a/migration/ram.c b/migration/ram.c
index 57368e1..efc215a 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -1051,6 +1051,44 @@  static void reset_ram_globals(void)
 
 #define MAX_WAIT 50 /* ms, half buffered_file limit */
 
+/*
+ * 'expected' is the value you expect the bitmap mostly to be full
+ * of; it won't bother printing lines that are all this value.
+ * If 'todump' is null the migration bitmap is dumped.
+ */
+void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
+{
+    int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
+
+    int64_t cur;
+    int64_t linelen = 128;
+    char linebuf[129];
+
+    if (!todump) {
+        todump = migration_bitmap;
+    }
+
+    for (cur = 0; cur < ram_pages; cur += linelen) {
+        int64_t curb;
+        bool found = false;
+        /*
+         * Last line; catch the case where the line length
+         * is longer than remaining ram
+         */
+        if (cur + linelen > ram_pages) {
+            linelen = ram_pages - cur;
+        }
+        for (curb = 0; curb < linelen; curb++) {
+            bool thisbit = test_bit(cur + curb, todump);
+            linebuf[curb] = thisbit ? '1' : '.';
+            found = found || (thisbit != expected);
+        }
+        if (found) {
+            linebuf[curb] = '\0';
+            fprintf(stderr,  "0x%08" PRIx64 " : %s\n", cur, linebuf);
+        }
+    }
+}
 
 /* Each of ram_save_setup, ram_save_iterate and ram_save_complete has
  * long-running RCU critical section.  When rcu-reclaims in the code