All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v5 0/3] ramblock: add hmp command "info ramblock"
@ 2017-05-09 11:25 Peter Xu
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 1/3] ramblock: add RAMBLOCK_FOREACH() Peter Xu
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Peter Xu @ 2017-05-09 11:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Markus Armbruster, peterx, Dr. David Alan Gilbert

v5
- add r-b for Dave on first patch (which I forgot in v4, so I got it
  again)
- add one more patch to introduce size_to_str() as patch 2 [Dave]
- let the last patch use the new interface

v4:
- move page_size_to_str() into util/cutil.c [Dave]

v3:
- cast the three PRIx64 addresses using (uint64_t) [Fam]
- add more comment in patch 2 to emphasize that this command is only
  suitable for HMP, not QMP [Markus]

v2:
- replace "lx" with "PRIx64" in three places

Sometimes I would like to know ramblock info for a VM. This command
would help. It provides a way to dump ramblock info. Currently the
list is by default sorted by size, though I think it's good enough.

Please review, thanks.

Peter Xu (3):
  ramblock: add RAMBLOCK_FOREACH()
  utils: provide size_to_str()
  ramblock: add new hmp command "info ramblock"

 exec.c                 | 44 +++++++++++++++++++++++++++++++++-----------
 hmp-commands-info.hx   | 14 ++++++++++++++
 hmp.c                  |  6 ++++++
 hmp.h                  |  1 +
 include/exec/ramlist.h |  6 ++++++
 include/qemu-common.h  |  1 +
 migration/ram.c        | 15 ++++++++-------
 util/cutils.c          | 26 ++++++++++++++++++++++++++
 8 files changed, 95 insertions(+), 18 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v5 1/3] ramblock: add RAMBLOCK_FOREACH()
  2017-05-09 11:25 [Qemu-devel] [PATCH v5 0/3] ramblock: add hmp command "info ramblock" Peter Xu
@ 2017-05-09 11:25 ` Peter Xu
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 2/3] utils: provide size_to_str() Peter Xu
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 3/3] ramblock: add new hmp command "info ramblock" Peter Xu
  2 siblings, 0 replies; 6+ messages in thread
From: Peter Xu @ 2017-05-09 11:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Markus Armbruster, peterx, Dr. David Alan Gilbert

So that it can simplifies the iterators.

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 exec.c                 | 22 +++++++++++-----------
 include/exec/ramlist.h |  5 +++++
 migration/ram.c        | 15 ++++++++-------
 3 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/exec.c b/exec.c
index eac6085..50519ae 100644
--- a/exec.c
+++ b/exec.c
@@ -978,7 +978,7 @@ static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
     if (block && addr - block->offset < block->max_length) {
         return block;
     }
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         if (addr - block->offset < block->max_length) {
             goto found;
         }
@@ -1578,12 +1578,12 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
         return 0;
     }
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         ram_addr_t end, next = RAM_ADDR_MAX;
 
         end = block->offset + block->max_length;
 
-        QLIST_FOREACH_RCU(next_block, &ram_list.blocks, next) {
+        RAMBLOCK_FOREACH(next_block) {
             if (next_block->offset >= end) {
                 next = MIN(next, next_block->offset);
             }
@@ -1609,7 +1609,7 @@ unsigned long last_ram_page(void)
     ram_addr_t last = 0;
 
     rcu_read_lock();
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         last = MAX(last, block->offset + block->max_length);
     }
     rcu_read_unlock();
@@ -1659,7 +1659,7 @@ void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
     pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
 
     rcu_read_lock();
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         if (block != new_block &&
             !strcmp(block->idstr, new_block->idstr)) {
             fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
@@ -1693,7 +1693,7 @@ size_t qemu_ram_pagesize_largest(void)
     RAMBlock *block;
     size_t largest = 0;
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         largest = MAX(largest, qemu_ram_pagesize(block));
     }
 
@@ -1839,7 +1839,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
      * QLIST (which has an RCU-friendly variant) does not have insertion at
      * tail, so save the last element in last_block.
      */
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         last_block = block;
         if (block->max_length < new_block->max_length) {
             break;
@@ -2021,7 +2021,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
     int flags;
     void *area, *vaddr;
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         offset = addr - block->offset;
         if (offset < block->max_length) {
             vaddr = ramblock_ptr(block, offset);
@@ -2167,7 +2167,7 @@ RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
         goto found;
     }
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         /* This case append when the block is not mapped. */
         if (block->host == NULL) {
             continue;
@@ -2200,7 +2200,7 @@ RAMBlock *qemu_ram_block_by_name(const char *name)
 {
     RAMBlock *block;
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         if (!strcmp(name, block->idstr)) {
             return block;
         }
@@ -3424,7 +3424,7 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
     int ret = 0;
 
     rcu_read_lock();
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         ret = func(block->idstr, block->host, block->offset,
                    block->used_length, opaque);
         if (ret) {
diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h
index c59880d..f1c6b45 100644
--- a/include/exec/ramlist.h
+++ b/include/exec/ramlist.h
@@ -4,6 +4,7 @@
 #include "qemu/queue.h"
 #include "qemu/thread.h"
 #include "qemu/rcu.h"
+#include "qemu/rcu_queue.h"
 
 typedef struct RAMBlockNotifier RAMBlockNotifier;
 
@@ -54,6 +55,10 @@ typedef struct RAMList {
 } RAMList;
 extern RAMList ram_list;
 
+/* Should be holding either ram_list.mutex, or the RCU lock. */
+#define  RAMBLOCK_FOREACH(block)  \
+    QLIST_FOREACH_RCU(block, &ram_list.blocks, next)
+
 void qemu_mutex_lock_ramlist(void);
 void qemu_mutex_unlock_ramlist(void);
 
diff --git a/migration/ram.c b/migration/ram.c
index f48664e..7ba5d7e 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -672,7 +672,7 @@ uint64_t ram_pagesize_summary(void)
     RAMBlock *block;
     uint64_t summary = 0;
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         summary |= block->page_size;
     }
 
@@ -700,7 +700,7 @@ static void migration_bitmap_sync(RAMState *rs)
 
     qemu_mutex_lock(&rs->bitmap_mutex);
     rcu_read_lock();
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         migration_bitmap_sync_range(rs, block, 0, block->used_length);
     }
     rcu_read_unlock();
@@ -1439,8 +1439,9 @@ uint64_t ram_bytes_total(void)
     uint64_t total = 0;
 
     rcu_read_lock();
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next)
+    RAMBLOCK_FOREACH(block) {
         total += block->used_length;
+    }
     rcu_read_unlock();
     return total;
 }
@@ -1543,7 +1544,7 @@ void ram_postcopy_migrated_memory_release(MigrationState *ms)
     struct RAMBlock *block;
     unsigned long *bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         unsigned long first = block->offset >> TARGET_PAGE_BITS;
         unsigned long range = first + (block->used_length >> TARGET_PAGE_BITS);
         unsigned long run_start = find_next_zero_bit(bitmap, range, first);
@@ -1624,7 +1625,7 @@ static int postcopy_each_ram_send_discard(MigrationState *ms)
     struct RAMBlock *block;
     int ret;
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         unsigned long first = block->offset >> TARGET_PAGE_BITS;
         PostcopyDiscardState *pds = postcopy_discard_send_init(ms,
                                                                first,
@@ -1802,7 +1803,7 @@ static int postcopy_chunk_hostpages(MigrationState *ms)
     rs->last_sent_block = NULL;
     rs->last_page = 0;
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         unsigned long first = block->offset >> TARGET_PAGE_BITS;
 
         PostcopyDiscardState *pds =
@@ -2021,7 +2022,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
 
     qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
 
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+    RAMBLOCK_FOREACH(block) {
         qemu_put_byte(f, strlen(block->idstr));
         qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
         qemu_put_be64(f, block->used_length);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v5 2/3] utils: provide size_to_str()
  2017-05-09 11:25 [Qemu-devel] [PATCH v5 0/3] ramblock: add hmp command "info ramblock" Peter Xu
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 1/3] ramblock: add RAMBLOCK_FOREACH() Peter Xu
@ 2017-05-09 11:25 ` Peter Xu
  2017-05-09 14:50   ` Markus Armbruster
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 3/3] ramblock: add new hmp command "info ramblock" Peter Xu
  2 siblings, 1 reply; 6+ messages in thread
From: Peter Xu @ 2017-05-09 11:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Markus Armbruster, peterx, Dr. David Alan Gilbert

I stole the algorithm from print_type_size(). I didn't generalize it
since that's using [KM...]iB while here we need [KM...]B to finally
be able to stands for page sizes (and even more general).

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/qemu-common.h |  1 +
 util/cutils.c         | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/qemu-common.h b/include/qemu-common.h
index d218821..d7d0448 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -145,6 +145,7 @@ void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
 int parse_debug_env(const char *name, int max, int initial);
 
 const char *qemu_ether_ntoa(const MACAddr *mac);
+char *size_to_str(double val);
 void page_size_init(void);
 
 /* returns non-zero if dump is in progress, otherwise zero is
diff --git a/util/cutils.c b/util/cutils.c
index 50ad179..5aaf370 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -619,3 +619,29 @@ const char *qemu_ether_ntoa(const MACAddr *mac)
 
     return ret;
 }
+
+/*
+ * Sample output:
+ *
+ * 1          -> "1 B"
+ * 528        -> "0.516 KB"
+ * 4096       -> "4 KB"
+ * 2402958    -> "2.29 MB"
+ * 1073741824 -> "1 GB"
+ *
+ * Please free the buffer after use.
+ */
+char *size_to_str(double val)
+{
+    static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E' };
+    unsigned long div;
+    int i;
+
+    frexp(val, &i);
+    i /= 10;
+    assert(i < sizeof(suffixes));
+    div = 1ULL << (i * 10);
+
+    return g_strdup_printf("%0.3g %c%s", val / div,
+                           suffixes[i], i ? "B" : "");
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v5 3/3] ramblock: add new hmp command "info ramblock"
  2017-05-09 11:25 [Qemu-devel] [PATCH v5 0/3] ramblock: add hmp command "info ramblock" Peter Xu
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 1/3] ramblock: add RAMBLOCK_FOREACH() Peter Xu
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 2/3] utils: provide size_to_str() Peter Xu
@ 2017-05-09 11:25 ` Peter Xu
  2 siblings, 0 replies; 6+ messages in thread
From: Peter Xu @ 2017-05-09 11:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Markus Armbruster, peterx, Dr. David Alan Gilbert

To dump information about ramblocks. It looks like:

(qemu) info ramblock
              Block Name    PSize              Offset               Used              Total
            /objects/mem     2 MB  0x0000000000000000 0x0000000080000000 0x0000000080000000
                vga.vram     4 KB  0x0000000080060000 0x0000000001000000 0x0000000001000000
    /rom@etc/acpi/tables     4 KB  0x00000000810b0000 0x0000000000020000 0x0000000000200000
                 pc.bios     4 KB  0x0000000080000000 0x0000000000040000 0x0000000000040000
  0000:00:03.0/e1000.rom     4 KB  0x0000000081070000 0x0000000000040000 0x0000000000040000
                  pc.rom     4 KB  0x0000000080040000 0x0000000000020000 0x0000000000020000
    0000:00:02.0/vga.rom     4 KB  0x0000000081060000 0x0000000000010000 0x0000000000010000
   /rom@etc/table-loader     4 KB  0x00000000812b0000 0x0000000000001000 0x0000000000001000
      /rom@etc/acpi/rsdp     4 KB  0x00000000812b1000 0x0000000000001000 0x0000000000001000

Ramblock is something hidden internally in QEMU implementation, and this
command should only be used by mostly QEMU developers on RAM stuff. It
is not a command suitable for QMP interface. So only HMP interface is
provided for it.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 exec.c                 | 22 ++++++++++++++++++++++
 hmp-commands-info.hx   | 14 ++++++++++++++
 hmp.c                  |  6 ++++++
 hmp.h                  |  1 +
 include/exec/ramlist.h |  1 +
 5 files changed, 44 insertions(+)

diff --git a/exec.c b/exec.c
index 50519ae..821bef3 100644
--- a/exec.c
+++ b/exec.c
@@ -71,6 +71,8 @@
 #include "qemu/mmap-alloc.h"
 #endif
 
+#include "monitor/monitor.h"
+
 //#define DEBUG_SUBPAGE
 
 #if !defined(CONFIG_USER_ONLY)
@@ -1333,6 +1335,26 @@ void qemu_mutex_unlock_ramlist(void)
     qemu_mutex_unlock(&ram_list.mutex);
 }
 
+void ram_block_dump(Monitor *mon)
+{
+    RAMBlock *block;
+    char *psize;
+
+    rcu_read_lock();
+    monitor_printf(mon, "%24s %8s  %18s %18s %18s\n",
+                   "Block Name", "PSize", "Offset", "Used", "Total");
+    RAMBLOCK_FOREACH(block) {
+        psize = size_to_str(block->page_size);
+        monitor_printf(mon, "%24s %8s  0x%016" PRIx64 " 0x%016" PRIx64
+                       " 0x%016" PRIx64 "\n", block->idstr, psize,
+                       (uint64_t)block->offset,
+                       (uint64_t)block->used_length,
+                       (uint64_t)block->max_length);
+        g_free(psize);
+    }
+    rcu_read_unlock();
+}
+
 #ifdef __linux__
 /*
  * FIXME TOCTTOU: this iterates over memory backends' mem-path, which
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index a53f105..ae16901 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -788,6 +788,20 @@ Display the latest dump status.
 ETEXI
 
     {
+        .name       = "ramblock",
+        .args_type  = "",
+        .params     = "",
+        .help       = "Display system ramblock information",
+        .cmd        = hmp_info_ramblock,
+    },
+
+STEXI
+@item info ramblock
+@findex ramblock
+Dump all the ramblocks of the system.
+ETEXI
+
+    {
         .name       = "hotpluggable-cpus",
         .args_type  = "",
         .params     = "",
diff --git a/hmp.c b/hmp.c
index ab407d6..8369388 100644
--- a/hmp.c
+++ b/hmp.c
@@ -37,6 +37,7 @@
 #include "qemu-io.h"
 #include "qemu/cutils.h"
 #include "qemu/error-report.h"
+#include "exec/ramlist.h"
 #include "hw/intc/intc.h"
 
 #ifdef CONFIG_SPICE
@@ -2563,6 +2564,11 @@ void hmp_info_dump(Monitor *mon, const QDict *qdict)
     qapi_free_DumpQueryResult(result);
 }
 
+void hmp_info_ramblock(Monitor *mon, const QDict *qdict)
+{
+    ram_block_dump(mon);
+}
+
 void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict)
 {
     Error *err = NULL;
diff --git a/hmp.h b/hmp.h
index 799fd37..7353b67 100644
--- a/hmp.h
+++ b/hmp.h
@@ -136,6 +136,7 @@ void hmp_rocker_ports(Monitor *mon, const QDict *qdict);
 void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict);
 void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict);
 void hmp_info_dump(Monitor *mon, const QDict *qdict);
+void hmp_info_ramblock(Monitor *mon, const QDict *qdict);
 void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict);
 void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict);
 
diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h
index f1c6b45..2e2ac6c 100644
--- a/include/exec/ramlist.h
+++ b/include/exec/ramlist.h
@@ -73,5 +73,6 @@ void ram_block_notifier_remove(RAMBlockNotifier *n);
 void ram_block_notify_add(void *host, size_t size);
 void ram_block_notify_remove(void *host, size_t size);
 
+void ram_block_dump(Monitor *mon);
 
 #endif /* RAMLIST_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/3] utils: provide size_to_str()
  2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 2/3] utils: provide size_to_str() Peter Xu
@ 2017-05-09 14:50   ` Markus Armbruster
  2017-05-10  3:32     ` Peter Xu
  0 siblings, 1 reply; 6+ messages in thread
From: Markus Armbruster @ 2017-05-09 14:50 UTC (permalink / raw)
  To: Peter Xu; +Cc: qemu-devel, Paolo Bonzini, Dr. David Alan Gilbert

Peter Xu <peterx@redhat.com> writes:

> I stole the algorithm from print_type_size(). I didn't generalize it
> since that's using [KM...]iB while here we need [KM...]B to finally
> be able to stands for page sizes (and even more general).

Can you explain why we need units without the 'i' here?

>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  include/qemu-common.h |  1 +
>  util/cutils.c         | 26 ++++++++++++++++++++++++++
>  2 files changed, 27 insertions(+)
>
> diff --git a/include/qemu-common.h b/include/qemu-common.h
> index d218821..d7d0448 100644
> --- a/include/qemu-common.h
> +++ b/include/qemu-common.h
> @@ -145,6 +145,7 @@ void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
>  int parse_debug_env(const char *name, int max, int initial);
>  
>  const char *qemu_ether_ntoa(const MACAddr *mac);
> +char *size_to_str(double val);
>  void page_size_init(void);
>  
>  /* returns non-zero if dump is in progress, otherwise zero is
> diff --git a/util/cutils.c b/util/cutils.c
> index 50ad179..5aaf370 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -619,3 +619,29 @@ const char *qemu_ether_ntoa(const MACAddr *mac)
>  
>      return ret;
>  }
> +
> +/*
> + * Sample output:
> + *
> + * 1          -> "1 B"
> + * 528        -> "0.516 KB"
> + * 4096       -> "4 KB"
> + * 2402958    -> "2.29 MB"
> + * 1073741824 -> "1 GB"
> + *
> + * Please free the buffer after use.
> + */
> +char *size_to_str(double val)
> +{
> +    static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E' };
> +    unsigned long div;
> +    int i;
> +
> +    frexp(val, &i);

The ignored return value is in [0.5,1), and multiplying it by 2^i yields
val.  i is close to the binary logarithm.

> +    i /= 10;

Now it's close to base-1024 logarithm.

Figuring this out requires too much thought for comfort.  Recommend
steal the comment from print_type_size(), too.

> +    assert(i < sizeof(suffixes));
> +    div = 1ULL << (i * 10);
> +
> +    return g_strdup_printf("%0.3g %c%s", val / div,
> +                           suffixes[i], i ? "B" : "");

The conditional is a bit confusing.  To avoid it, we could make
suffixes[] an array of strings, with suffixes[0] = "".

> +}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/3] utils: provide size_to_str()
  2017-05-09 14:50   ` Markus Armbruster
@ 2017-05-10  3:32     ` Peter Xu
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Xu @ 2017-05-10  3:32 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Paolo Bonzini, Dr. David Alan Gilbert

On Tue, May 09, 2017 at 04:50:26PM +0200, Markus Armbruster wrote:
> Peter Xu <peterx@redhat.com> writes:
> 
> > I stole the algorithm from print_type_size(). I didn't generalize it
> > since that's using [KM...]iB while here we need [KM...]B to finally
> > be able to stands for page sizes (and even more general).
> 
> Can you explain why we need units without the 'i' here?

Oops. I misunderstood XiB... My fault. Page sizes needs exactly "i".

> 
> >
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >  include/qemu-common.h |  1 +
> >  util/cutils.c         | 26 ++++++++++++++++++++++++++
> >  2 files changed, 27 insertions(+)
> >
> > diff --git a/include/qemu-common.h b/include/qemu-common.h
> > index d218821..d7d0448 100644
> > --- a/include/qemu-common.h
> > +++ b/include/qemu-common.h
> > @@ -145,6 +145,7 @@ void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
> >  int parse_debug_env(const char *name, int max, int initial);
> >  
> >  const char *qemu_ether_ntoa(const MACAddr *mac);
> > +char *size_to_str(double val);
> >  void page_size_init(void);
> >  
> >  /* returns non-zero if dump is in progress, otherwise zero is
> > diff --git a/util/cutils.c b/util/cutils.c
> > index 50ad179..5aaf370 100644
> > --- a/util/cutils.c
> > +++ b/util/cutils.c
> > @@ -619,3 +619,29 @@ const char *qemu_ether_ntoa(const MACAddr *mac)
> >  
> >      return ret;
> >  }
> > +
> > +/*
> > + * Sample output:
> > + *
> > + * 1          -> "1 B"
> > + * 528        -> "0.516 KB"
> > + * 4096       -> "4 KB"
> > + * 2402958    -> "2.29 MB"
> > + * 1073741824 -> "1 GB"
> > + *
> > + * Please free the buffer after use.
> > + */
> > +char *size_to_str(double val)
> > +{
> > +    static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E' };
> > +    unsigned long div;
> > +    int i;
> > +
> > +    frexp(val, &i);
> 
> The ignored return value is in [0.5,1), and multiplying it by 2^i yields
> val.  i is close to the binary logarithm.
> 
> > +    i /= 10;
> 
> Now it's close to base-1024 logarithm.
> 
> Figuring this out requires too much thought for comfort.  Recommend
> steal the comment from print_type_size(), too.

Let me do it even simpler - I'll just move the whole logic in
print_type_size() into size_to_str(), then I'll refactor
print_type_size().

> 
> > +    assert(i < sizeof(suffixes));
> > +    div = 1ULL << (i * 10);
> > +
> > +    return g_strdup_printf("%0.3g %c%s", val / div,
> > +                           suffixes[i], i ? "B" : "");
> 
> The conditional is a bit confusing.  To avoid it, we could make
> suffixes[] an array of strings, with suffixes[0] = "".

I can fix this. Thanks reviewing!

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-05-10  3:32 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-09 11:25 [Qemu-devel] [PATCH v5 0/3] ramblock: add hmp command "info ramblock" Peter Xu
2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 1/3] ramblock: add RAMBLOCK_FOREACH() Peter Xu
2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 2/3] utils: provide size_to_str() Peter Xu
2017-05-09 14:50   ` Markus Armbruster
2017-05-10  3:32     ` Peter Xu
2017-05-09 11:25 ` [Qemu-devel] [PATCH v5 3/3] ramblock: add new hmp command "info ramblock" Peter Xu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.