[Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"

Alexey Kardashevskiy posted 1 patch 6 years ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20180329032149.44685-1-aik@ozlabs.ru
Test checkpatch passed
Test docker-build@min-glib failed
Test docker-mingw@fedora passed
Test docker-quick@centos6 failed
Test s390x passed
include/exec/memory.h |  2 +-
memory.c              | 80 ++++++++++++++++++++++++++++++++++++++++++++-------
monitor.c             |  4 ++-
hmp-commands-info.hx  |  7 +++--
4 files changed, 78 insertions(+), 15 deletions(-)
[Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Alexey Kardashevskiy 6 years ago
This adds owners/parents (which are the same, just occasionally
owner==NULL) printing for memory regions; a new '-o' flag
enabled new output.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---

Does this look anything useful?

There are cases ("msi", "msix-table", "msix-pba" and probably more) when
it is not clear what owns an MR while they all have an owner (always? mostly?).


"info mtree" example:

address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system parent:{obj}
    0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram parent:{obj}
    0000200000000000-000020000000ffff (prio 0, i/o): alias pci@800000020000000.io-alias @pci@800000020000000.io 0000000000000000-000000000000ffff owner:{dev path=/machine/unattached/device[3]}
    0000200080000000-00002000ffffffff (prio 0, i/o): alias pci@800000020000000.mmio32-alias @pci@800000020000000.mmio 0000000080000000-00000000ffffffff owner:{dev path=/machine/unattached/device[3]}
    0000210000000000-000021ffffffffff (prio 0, i/o): alias pci@800000020000000.mmio64-alias @pci@800000020000000.mmio 0000210000000000-000021ffffffffff owner:{dev path=/machine/unattached/device[3]}

address-space: I/O
  0000000000000000-000000000000ffff (prio 0, i/o): io parent:{obj}

address-space: cpu-memory-0
  0000000000000000-ffffffffffffffff (prio 0, i/o): system parent:{obj}
    0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram parent:{obj}
    0000200000000000-000020000000ffff (prio 0, i/o): alias pci@800000020000000.io-alias @pci@800000020000000.io 0000000000000000-000000000000ffff owner:{dev path=/machine/unattached/device[3]}
    0000200080000000-00002000ffffffff (prio 0, i/o): alias pci@800000020000000.mmio32-alias @pci@800000020000000.mmio 0000000080000000-00000000ffffffff owner:{dev path=/machine/unattached/device[3]}
    0000210000000000-000021ffffffffff (prio 0, i/o): alias pci@800000020000000.mmio64-alias @pci@800000020000000.mmio 0000210000000000-000021ffffffffff owner:{dev path=/machine/unattached/device[3]}

address-space: pci@800000020000000
  0000000000000000-ffffffffffffffff (prio 0, i/o): pci@800000020000000.iommu-root owner:{dev path=/machine/unattached/device[3]}
    0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
      0800000000000000-080000007fffffff (prio 0, i/o): tce-iommu-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
    0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
      0000000000000000-000000003fffffff (prio 0, i/o): tce-iommu-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
    0000040000000000-000004000000ffff (prio 0, i/o): msi owner:{dev path=/machine/unattached/device[3]}

address-space: vfio-pci
  0000000000000000-ffffffffffffffff (prio 0, i/o): bus master container owner:{dev id=vfio0001_03_00_0}
    0000000000000000-ffffffffffffffff (prio 0, i/o): alias bus master @pci@800000020000000.iommu-root 0000000000000000-ffffffffffffffff owner:{dev id=vfio0001_03_00_0}

memory-region: pci@800000020000000.io
  0000000000000000-000000000000ffff (prio 0, i/o): pci@800000020000000.io owner:{dev path=/machine/unattached/device[3]}

memory-region: pci@800000020000000.mmio
  0000000000000000-ffffffffffffffff (prio 0, i/o): pci@800000020000000.mmio owner:{dev path=/machine/unattached/device[3]}
    0000210000000000-000021000000ffff (prio 1, i/o): 0001:03:00.0 base BAR 1 owner:{dev id=vfio0001_03_00_0}
      0000210000000000-000021000000ffff (prio 0, i/o): 0001:03:00.0 BAR 1 owner:{dev id=vfio0001_03_00_0}
      000021000000e000-000021000000e5ff (prio 0, i/o): msix-table owner:{dev id=vfio0001_03_00_0}
      000021000000f000-000021000000f00f (prio 0, i/o): msix-pba [disabled] owner:{dev id=vfio0001_03_00_0}
    0000210000040000-000021000007ffff (prio 1, i/o): 0001:03:00.0 base BAR 3 owner:{dev id=vfio0001_03_00_0}
      0000210000040000-000021000007ffff (prio 0, i/o): 0001:03:00.0 BAR 3 owner:{dev id=vfio0001_03_00_0}
        0000210000040000-000021000007ffff (prio 0, ramd): 0001:03:00.0 BAR 3 mmaps[0] owner:{dev id=vfio0001_03_00_0}

memory-region: pci@800000020000000.iommu-root
  0000000000000000-ffffffffffffffff (prio 0, i/o): pci@800000020000000.iommu-root owner:{dev path=/machine/unattached/device[3]}
    0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
      0800000000000000-080000007fffffff (prio 0, i/o): tce-iommu-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
    0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
      0000000000000000-000000003fffffff (prio 0, i/o): tce-iommu-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
    0000040000000000-000004000000ffff (prio 0, i/o): msi owner:{dev path=/machine/unattached/device[3]}



Flatviews:


FlatView #0
 AS "pci@800000020000000", root: pci@800000020000000.iommu-root
 AS "vfio-pci", root: bus master container
 Root memory region: pci@800000020000000.iommu-root
  0000000000000000-000000003fffffff (prio 0, i/o): tce-iommu-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
  0000040000000000-000004000000ffff (prio 0, i/o): msi owner:{dev path=/machine/unattached/device[3]}
  0800000000000000-080000007fffffff (prio 0, i/o): tce-iommu-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}

FlatView #1
 AS "memory", root: system
 AS "cpu-memory-0", root: system
 Root memory region: system
  0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram parent:{obj}
  0000210000000000-000021000000dfff (prio 0, i/o): 0001:03:00.0 BAR 1 owner:{dev id=vfio0001_03_00_0}
  000021000000e000-000021000000e5ff (prio 0, i/o): msix-table owner:{dev id=vfio0001_03_00_0}
  000021000000e600-000021000000ffff (prio 0, i/o): 0001:03:00.0 BAR 1 @000000000000e600 owner:{dev id=vfio0001_03_00_0}
  0000210000040000-000021000007ffff (prio 0, ramd): 0001:03:00.0 BAR 3 mmaps[0] owner:{dev id=vfio0001_03_00_0}

FlatView #2
 AS "I/O", root: io
 Root memory region: io
  0000000000000000-000000000000ffff (prio 0, i/o): io parent:{obj}
---
 include/exec/memory.h |  2 +-
 memory.c              | 80 ++++++++++++++++++++++++++++++++++++++++++++-------
 monitor.c             |  4 ++-
 hmp-commands-info.hx  |  7 +++--
 4 files changed, 78 insertions(+), 15 deletions(-)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 31eae0a..3e9d67c 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1541,7 +1541,7 @@ void memory_global_dirty_log_start(void);
 void memory_global_dirty_log_stop(void);
 
 void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
-                bool dispatch_tree);
+                bool dispatch_tree, bool owner);
 
 /**
  * memory_region_request_mmio_ptr: request a pointer to an mmio
diff --git a/memory.c b/memory.c
index e70b64b..538a57c 100644
--- a/memory.c
+++ b/memory.c
@@ -2830,10 +2830,57 @@ typedef QTAILQ_HEAD(mrqueue, MemoryRegionList) MemoryRegionListHead;
                            int128_sub((size), int128_one())) : 0)
 #define MTREE_INDENT "  "
 
+static void mtree_expand_owner(fprintf_function mon_printf, void *f,
+                               const char *label, Object *obj)
+{
+    DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE);
+    const char *id = object_property_print(obj, "id", true, NULL);
+    const char *name = object_property_print(obj, "name", true, NULL);
+
+    mon_printf(f, " %s:{", label);
+    if (dev) {
+        mon_printf(f, "dev");
+        if (dev->id) {
+            mon_printf(f, " id=%s", dev->id);
+        }
+    } else {
+        mon_printf(f, "obj");
+    }
+    if (name) {
+        mon_printf(f, " name=%s ", name);
+    }
+    if (id) {
+        mon_printf(f, " id=%s ", id);
+    }
+    if (dev && (!name && !id && !dev->id)) {
+        mon_printf(f, " path=%s", dev->canonical_path);
+    }
+    mon_printf(f, "}");
+}
+
+static void mtree_print_mr_owner(fprintf_function mon_printf, void *f,
+                                 const MemoryRegion *mr)
+{
+    Object *owner = mr->owner;
+    Object *parent = memory_region_owner((MemoryRegion *)mr);
+
+    if (!owner && !parent) {
+        mon_printf(f, " orphan");
+        return;
+    }
+    if (owner) {
+        mtree_expand_owner(mon_printf, f, "owner", owner);
+    }
+    if (parent && parent != owner) {
+        mtree_expand_owner(mon_printf, f, "parent", parent);
+    }
+}
+
 static void mtree_print_mr(fprintf_function mon_printf, void *f,
                            const MemoryRegion *mr, unsigned int level,
                            hwaddr base,
-                           MemoryRegionListHead *alias_print_queue)
+                           MemoryRegionListHead *alias_print_queue,
+                           bool owner)
 {
     MemoryRegionList *new_ml, *ml, *next_ml;
     MemoryRegionListHead submr_print_queue;
@@ -2879,7 +2926,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
         }
         mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
                    " (prio %d, %s): alias %s @%s " TARGET_FMT_plx
-                   "-" TARGET_FMT_plx "%s\n",
+                   "-" TARGET_FMT_plx "%s",
                    cur_start, cur_end,
                    mr->priority,
                    memory_region_type((MemoryRegion *)mr),
@@ -2888,15 +2935,22 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
                    mr->alias_offset,
                    mr->alias_offset + MR_SIZE(mr->size),
                    mr->enabled ? "" : " [disabled]");
+        if (owner) {
+            mtree_print_mr_owner(mon_printf, f, mr);
+        }
     } else {
         mon_printf(f,
-                   TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s\n",
+                   TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s",
                    cur_start, cur_end,
                    mr->priority,
                    memory_region_type((MemoryRegion *)mr),
                    memory_region_name(mr),
                    mr->enabled ? "" : " [disabled]");
+        if (owner) {
+            mtree_print_mr_owner(mon_printf, f, mr);
+        }
     }
+    mon_printf(f, "\n");
 
     QTAILQ_INIT(&submr_print_queue);
 
@@ -2919,7 +2973,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
 
     QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
         mtree_print_mr(mon_printf, f, ml->mr, level + 1, cur_start,
-                       alias_print_queue);
+                       alias_print_queue, owner);
     }
 
     QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, mrqueue, next_ml) {
@@ -2932,6 +2986,7 @@ struct FlatViewInfo {
     void *f;
     int counter;
     bool dispatch_tree;
+    bool owner;
 };
 
 static void mtree_print_flatview(gpointer key, gpointer value,
@@ -2972,7 +3027,7 @@ static void mtree_print_flatview(gpointer key, gpointer value,
         mr = range->mr;
         if (range->offset_in_region) {
             p(f, MTREE_INDENT TARGET_FMT_plx "-"
-              TARGET_FMT_plx " (prio %d, %s): %s @" TARGET_FMT_plx "\n",
+              TARGET_FMT_plx " (prio %d, %s): %s @" TARGET_FMT_plx,
               int128_get64(range->addr.start),
               int128_get64(range->addr.start) + MR_SIZE(range->addr.size),
               mr->priority,
@@ -2981,13 +3036,17 @@ static void mtree_print_flatview(gpointer key, gpointer value,
               range->offset_in_region);
         } else {
             p(f, MTREE_INDENT TARGET_FMT_plx "-"
-              TARGET_FMT_plx " (prio %d, %s): %s\n",
+              TARGET_FMT_plx " (prio %d, %s): %s",
               int128_get64(range->addr.start),
               int128_get64(range->addr.start) + MR_SIZE(range->addr.size),
               mr->priority,
               range->readonly ? "rom" : memory_region_type(mr),
               memory_region_name(mr));
         }
+        if (fvi->owner) {
+            mtree_print_mr_owner(p, f, mr);
+        }
+        p(f, "\n");
         range++;
     }
 
@@ -3013,7 +3072,7 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value,
 }
 
 void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
-                bool dispatch_tree)
+                bool dispatch_tree, bool owner)
 {
     MemoryRegionListHead ml_head;
     MemoryRegionList *ml, *ml2;
@@ -3025,7 +3084,8 @@ void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
             .mon_printf = mon_printf,
             .f = f,
             .counter = 0,
-            .dispatch_tree = dispatch_tree
+            .dispatch_tree = dispatch_tree,
+            .owner = owner,
         };
         GArray *fv_address_spaces;
         GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -3057,14 +3117,14 @@ void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
 
     QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
         mon_printf(f, "address-space: %s\n", as->name);
-        mtree_print_mr(mon_printf, f, as->root, 1, 0, &ml_head);
+        mtree_print_mr(mon_printf, f, as->root, 1, 0, &ml_head, owner);
         mon_printf(f, "\n");
     }
 
     /* print aliased regions */
     QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
         mon_printf(f, "memory-region: %s\n", memory_region_name(ml->mr));
-        mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head);
+        mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head, owner);
         mon_printf(f, "\n");
     }
 
diff --git a/monitor.c b/monitor.c
index 51f4cf4..9d304a5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1969,8 +1969,10 @@ static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
 {
     bool flatview = qdict_get_try_bool(qdict, "flatview", false);
     bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
+    bool owner = qdict_get_try_bool(qdict, "owner", false);
 
-    mtree_info((fprintf_function)monitor_printf, mon, flatview, dispatch_tree);
+    mtree_info((fprintf_function)monitor_printf, mon, flatview, dispatch_tree,
+               owner);
 }
 
 static void hmp_info_numa(Monitor *mon, const QDict *qdict)
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index ddfcd5a..5956495 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -250,10 +250,11 @@ ETEXI
 
     {
         .name       = "mtree",
-        .args_type  = "flatview:-f,dispatch_tree:-d",
-        .params     = "[-f][-d]",
+        .args_type  = "flatview:-f,dispatch_tree:-d,owner:-o",
+        .params     = "[-f][-d][-o]",
         .help       = "show memory tree (-f: dump flat view for address spaces;"
-                      "-d: dump dispatch tree, valid with -f only)",
+                      "-d: dump dispatch tree, valid with -f only);"
+                      "-o: dump region owners/parents",
         .cmd        = hmp_info_mtree,
     },
 
-- 
2.11.0


Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Dr. David Alan Gilbert 6 years ago
* Alexey Kardashevskiy (aik@ozlabs.ru) wrote:
> This adds owners/parents (which are the same, just occasionally
> owner==NULL) printing for memory regions; a new '-o' flag
> enabled new output.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>

From the HMP side this looks fine to me, and if it's making it clearer
where mappings are coming from that's good.
(It's a bit long/wordy, but that's the nature of the information).



Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

> ---
> 
> Does this look anything useful?
> 
> There are cases ("msi", "msix-table", "msix-pba" and probably more) when
> it is not clear what owns an MR while they all have an owner (always? mostly?).
> 
> 
> "info mtree" example:
> 
> address-space: memory
>   0000000000000000-ffffffffffffffff (prio 0, i/o): system parent:{obj}
>     0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram parent:{obj}
>     0000200000000000-000020000000ffff (prio 0, i/o): alias pci@800000020000000.io-alias @pci@800000020000000.io 0000000000000000-000000000000ffff owner:{dev path=/machine/unattached/device[3]}
>     0000200080000000-00002000ffffffff (prio 0, i/o): alias pci@800000020000000.mmio32-alias @pci@800000020000000.mmio 0000000080000000-00000000ffffffff owner:{dev path=/machine/unattached/device[3]}
>     0000210000000000-000021ffffffffff (prio 0, i/o): alias pci@800000020000000.mmio64-alias @pci@800000020000000.mmio 0000210000000000-000021ffffffffff owner:{dev path=/machine/unattached/device[3]}
> 
> address-space: I/O
>   0000000000000000-000000000000ffff (prio 0, i/o): io parent:{obj}
> 
> address-space: cpu-memory-0
>   0000000000000000-ffffffffffffffff (prio 0, i/o): system parent:{obj}
>     0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram parent:{obj}
>     0000200000000000-000020000000ffff (prio 0, i/o): alias pci@800000020000000.io-alias @pci@800000020000000.io 0000000000000000-000000000000ffff owner:{dev path=/machine/unattached/device[3]}
>     0000200080000000-00002000ffffffff (prio 0, i/o): alias pci@800000020000000.mmio32-alias @pci@800000020000000.mmio 0000000080000000-00000000ffffffff owner:{dev path=/machine/unattached/device[3]}
>     0000210000000000-000021ffffffffff (prio 0, i/o): alias pci@800000020000000.mmio64-alias @pci@800000020000000.mmio 0000210000000000-000021ffffffffff owner:{dev path=/machine/unattached/device[3]}
> 
> address-space: pci@800000020000000
>   0000000000000000-ffffffffffffffff (prio 0, i/o): pci@800000020000000.iommu-root owner:{dev path=/machine/unattached/device[3]}
>     0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
>       0800000000000000-080000007fffffff (prio 0, i/o): tce-iommu-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
>     0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
>       0000000000000000-000000003fffffff (prio 0, i/o): tce-iommu-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
>     0000040000000000-000004000000ffff (prio 0, i/o): msi owner:{dev path=/machine/unattached/device[3]}
> 
> address-space: vfio-pci
>   0000000000000000-ffffffffffffffff (prio 0, i/o): bus master container owner:{dev id=vfio0001_03_00_0}
>     0000000000000000-ffffffffffffffff (prio 0, i/o): alias bus master @pci@800000020000000.iommu-root 0000000000000000-ffffffffffffffff owner:{dev id=vfio0001_03_00_0}
> 
> memory-region: pci@800000020000000.io
>   0000000000000000-000000000000ffff (prio 0, i/o): pci@800000020000000.io owner:{dev path=/machine/unattached/device[3]}
> 
> memory-region: pci@800000020000000.mmio
>   0000000000000000-ffffffffffffffff (prio 0, i/o): pci@800000020000000.mmio owner:{dev path=/machine/unattached/device[3]}
>     0000210000000000-000021000000ffff (prio 1, i/o): 0001:03:00.0 base BAR 1 owner:{dev id=vfio0001_03_00_0}
>       0000210000000000-000021000000ffff (prio 0, i/o): 0001:03:00.0 BAR 1 owner:{dev id=vfio0001_03_00_0}
>       000021000000e000-000021000000e5ff (prio 0, i/o): msix-table owner:{dev id=vfio0001_03_00_0}
>       000021000000f000-000021000000f00f (prio 0, i/o): msix-pba [disabled] owner:{dev id=vfio0001_03_00_0}
>     0000210000040000-000021000007ffff (prio 1, i/o): 0001:03:00.0 base BAR 3 owner:{dev id=vfio0001_03_00_0}
>       0000210000040000-000021000007ffff (prio 0, i/o): 0001:03:00.0 BAR 3 owner:{dev id=vfio0001_03_00_0}
>         0000210000040000-000021000007ffff (prio 0, ramd): 0001:03:00.0 BAR 3 mmaps[0] owner:{dev id=vfio0001_03_00_0}
> 
> memory-region: pci@800000020000000.iommu-root
>   0000000000000000-ffffffffffffffff (prio 0, i/o): pci@800000020000000.iommu-root owner:{dev path=/machine/unattached/device[3]}
>     0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
>       0800000000000000-080000007fffffff (prio 0, i/o): tce-iommu-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
>     0000000000000000-ffffffffffffffff (prio 0, i/o): tce-root-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
>       0000000000000000-000000003fffffff (prio 0, i/o): tce-iommu-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
>     0000040000000000-000004000000ffff (prio 0, i/o): msi owner:{dev path=/machine/unattached/device[3]}
> 
> 
> 
> Flatviews:
> 
> 
> FlatView #0
>  AS "pci@800000020000000", root: pci@800000020000000.iommu-root
>  AS "vfio-pci", root: bus master container
>  Root memory region: pci@800000020000000.iommu-root
>   0000000000000000-000000003fffffff (prio 0, i/o): tce-iommu-80000000 owner:{dev path=/machine/unattached/device[3]/tce-table-80000000}
>   0000040000000000-000004000000ffff (prio 0, i/o): msi owner:{dev path=/machine/unattached/device[3]}
>   0800000000000000-080000007fffffff (prio 0, i/o): tce-iommu-80000001 owner:{dev path=/machine/unattached/device[3]/tce-table-80000001}
> 
> FlatView #1
>  AS "memory", root: system
>  AS "cpu-memory-0", root: system
>  Root memory region: system
>   0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram parent:{obj}
>   0000210000000000-000021000000dfff (prio 0, i/o): 0001:03:00.0 BAR 1 owner:{dev id=vfio0001_03_00_0}
>   000021000000e000-000021000000e5ff (prio 0, i/o): msix-table owner:{dev id=vfio0001_03_00_0}
>   000021000000e600-000021000000ffff (prio 0, i/o): 0001:03:00.0 BAR 1 @000000000000e600 owner:{dev id=vfio0001_03_00_0}
>   0000210000040000-000021000007ffff (prio 0, ramd): 0001:03:00.0 BAR 3 mmaps[0] owner:{dev id=vfio0001_03_00_0}
> 
> FlatView #2
>  AS "I/O", root: io
>  Root memory region: io
>   0000000000000000-000000000000ffff (prio 0, i/o): io parent:{obj}
> ---
>  include/exec/memory.h |  2 +-
>  memory.c              | 80 ++++++++++++++++++++++++++++++++++++++++++++-------
>  monitor.c             |  4 ++-
>  hmp-commands-info.hx  |  7 +++--
>  4 files changed, 78 insertions(+), 15 deletions(-)
> 
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 31eae0a..3e9d67c 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -1541,7 +1541,7 @@ void memory_global_dirty_log_start(void);
>  void memory_global_dirty_log_stop(void);
>  
>  void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
> -                bool dispatch_tree);
> +                bool dispatch_tree, bool owner);
>  
>  /**
>   * memory_region_request_mmio_ptr: request a pointer to an mmio
> diff --git a/memory.c b/memory.c
> index e70b64b..538a57c 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -2830,10 +2830,57 @@ typedef QTAILQ_HEAD(mrqueue, MemoryRegionList) MemoryRegionListHead;
>                             int128_sub((size), int128_one())) : 0)
>  #define MTREE_INDENT "  "
>  
> +static void mtree_expand_owner(fprintf_function mon_printf, void *f,
> +                               const char *label, Object *obj)
> +{
> +    DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE);
> +    const char *id = object_property_print(obj, "id", true, NULL);
> +    const char *name = object_property_print(obj, "name", true, NULL);
> +
> +    mon_printf(f, " %s:{", label);
> +    if (dev) {
> +        mon_printf(f, "dev");
> +        if (dev->id) {
> +            mon_printf(f, " id=%s", dev->id);
> +        }
> +    } else {
> +        mon_printf(f, "obj");
> +    }
> +    if (name) {
> +        mon_printf(f, " name=%s ", name);
> +    }
> +    if (id) {
> +        mon_printf(f, " id=%s ", id);
> +    }
> +    if (dev && (!name && !id && !dev->id)) {
> +        mon_printf(f, " path=%s", dev->canonical_path);
> +    }
> +    mon_printf(f, "}");
> +}
> +
> +static void mtree_print_mr_owner(fprintf_function mon_printf, void *f,
> +                                 const MemoryRegion *mr)
> +{
> +    Object *owner = mr->owner;
> +    Object *parent = memory_region_owner((MemoryRegion *)mr);
> +
> +    if (!owner && !parent) {
> +        mon_printf(f, " orphan");
> +        return;
> +    }
> +    if (owner) {
> +        mtree_expand_owner(mon_printf, f, "owner", owner);
> +    }
> +    if (parent && parent != owner) {
> +        mtree_expand_owner(mon_printf, f, "parent", parent);
> +    }
> +}
> +
>  static void mtree_print_mr(fprintf_function mon_printf, void *f,
>                             const MemoryRegion *mr, unsigned int level,
>                             hwaddr base,
> -                           MemoryRegionListHead *alias_print_queue)
> +                           MemoryRegionListHead *alias_print_queue,
> +                           bool owner)
>  {
>      MemoryRegionList *new_ml, *ml, *next_ml;
>      MemoryRegionListHead submr_print_queue;
> @@ -2879,7 +2926,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
>          }
>          mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
>                     " (prio %d, %s): alias %s @%s " TARGET_FMT_plx
> -                   "-" TARGET_FMT_plx "%s\n",
> +                   "-" TARGET_FMT_plx "%s",
>                     cur_start, cur_end,
>                     mr->priority,
>                     memory_region_type((MemoryRegion *)mr),
> @@ -2888,15 +2935,22 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
>                     mr->alias_offset,
>                     mr->alias_offset + MR_SIZE(mr->size),
>                     mr->enabled ? "" : " [disabled]");
> +        if (owner) {
> +            mtree_print_mr_owner(mon_printf, f, mr);
> +        }
>      } else {
>          mon_printf(f,
> -                   TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s\n",
> +                   TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s",
>                     cur_start, cur_end,
>                     mr->priority,
>                     memory_region_type((MemoryRegion *)mr),
>                     memory_region_name(mr),
>                     mr->enabled ? "" : " [disabled]");
> +        if (owner) {
> +            mtree_print_mr_owner(mon_printf, f, mr);
> +        }
>      }
> +    mon_printf(f, "\n");
>  
>      QTAILQ_INIT(&submr_print_queue);
>  
> @@ -2919,7 +2973,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
>  
>      QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
>          mtree_print_mr(mon_printf, f, ml->mr, level + 1, cur_start,
> -                       alias_print_queue);
> +                       alias_print_queue, owner);
>      }
>  
>      QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, mrqueue, next_ml) {
> @@ -2932,6 +2986,7 @@ struct FlatViewInfo {
>      void *f;
>      int counter;
>      bool dispatch_tree;
> +    bool owner;
>  };
>  
>  static void mtree_print_flatview(gpointer key, gpointer value,
> @@ -2972,7 +3027,7 @@ static void mtree_print_flatview(gpointer key, gpointer value,
>          mr = range->mr;
>          if (range->offset_in_region) {
>              p(f, MTREE_INDENT TARGET_FMT_plx "-"
> -              TARGET_FMT_plx " (prio %d, %s): %s @" TARGET_FMT_plx "\n",
> +              TARGET_FMT_plx " (prio %d, %s): %s @" TARGET_FMT_plx,
>                int128_get64(range->addr.start),
>                int128_get64(range->addr.start) + MR_SIZE(range->addr.size),
>                mr->priority,
> @@ -2981,13 +3036,17 @@ static void mtree_print_flatview(gpointer key, gpointer value,
>                range->offset_in_region);
>          } else {
>              p(f, MTREE_INDENT TARGET_FMT_plx "-"
> -              TARGET_FMT_plx " (prio %d, %s): %s\n",
> +              TARGET_FMT_plx " (prio %d, %s): %s",
>                int128_get64(range->addr.start),
>                int128_get64(range->addr.start) + MR_SIZE(range->addr.size),
>                mr->priority,
>                range->readonly ? "rom" : memory_region_type(mr),
>                memory_region_name(mr));
>          }
> +        if (fvi->owner) {
> +            mtree_print_mr_owner(p, f, mr);
> +        }
> +        p(f, "\n");
>          range++;
>      }
>  
> @@ -3013,7 +3072,7 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value,
>  }
>  
>  void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
> -                bool dispatch_tree)
> +                bool dispatch_tree, bool owner)
>  {
>      MemoryRegionListHead ml_head;
>      MemoryRegionList *ml, *ml2;
> @@ -3025,7 +3084,8 @@ void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
>              .mon_printf = mon_printf,
>              .f = f,
>              .counter = 0,
> -            .dispatch_tree = dispatch_tree
> +            .dispatch_tree = dispatch_tree,
> +            .owner = owner,
>          };
>          GArray *fv_address_spaces;
>          GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
> @@ -3057,14 +3117,14 @@ void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
>  
>      QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
>          mon_printf(f, "address-space: %s\n", as->name);
> -        mtree_print_mr(mon_printf, f, as->root, 1, 0, &ml_head);
> +        mtree_print_mr(mon_printf, f, as->root, 1, 0, &ml_head, owner);
>          mon_printf(f, "\n");
>      }
>  
>      /* print aliased regions */
>      QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
>          mon_printf(f, "memory-region: %s\n", memory_region_name(ml->mr));
> -        mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head);
> +        mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head, owner);
>          mon_printf(f, "\n");
>      }
>  
> diff --git a/monitor.c b/monitor.c
> index 51f4cf4..9d304a5 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1969,8 +1969,10 @@ static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
>  {
>      bool flatview = qdict_get_try_bool(qdict, "flatview", false);
>      bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
> +    bool owner = qdict_get_try_bool(qdict, "owner", false);
>  
> -    mtree_info((fprintf_function)monitor_printf, mon, flatview, dispatch_tree);
> +    mtree_info((fprintf_function)monitor_printf, mon, flatview, dispatch_tree,
> +               owner);
>  }
>  
>  static void hmp_info_numa(Monitor *mon, const QDict *qdict)
> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
> index ddfcd5a..5956495 100644
> --- a/hmp-commands-info.hx
> +++ b/hmp-commands-info.hx
> @@ -250,10 +250,11 @@ ETEXI
>  
>      {
>          .name       = "mtree",
> -        .args_type  = "flatview:-f,dispatch_tree:-d",
> -        .params     = "[-f][-d]",
> +        .args_type  = "flatview:-f,dispatch_tree:-d,owner:-o",
> +        .params     = "[-f][-d][-o]",
>          .help       = "show memory tree (-f: dump flat view for address spaces;"
> -                      "-d: dump dispatch tree, valid with -f only)",
> +                      "-d: dump dispatch tree, valid with -f only);"
> +                      "-o: dump region owners/parents",
>          .cmd        = hmp_info_mtree,
>      },
>  
> -- 
> 2.11.0
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Paolo Bonzini 6 years ago
On 29/03/2018 05:21, Alexey Kardashevskiy wrote:
> +    DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE);
> +    const char *id = object_property_print(obj, "id", true, NULL);

I learnt now about commit e1ff3c67e8544f41f1bea76ba76385faee0d2bb7 and I
find it a mistake.  The "id" is available through
object_get_canonical_path_component.  Can you change the "id" assignment
to use object_get_canonical_path_component instead?

> +    const char *name = object_property_print(obj, "name", true, NULL);

Who defines a name property?

> +    mon_printf(f, " %s:{", label);
> +    if (dev) {
> +        mon_printf(f, "dev");
> +        if (dev->id) {
> +            mon_printf(f, " id=%s", dev->id);
> +        }
> +    } else {
> +        mon_printf(f, "obj");

> +    }
> +    if (name) {
> +        mon_printf(f, " name=%s ", name);
> +    }
> +    if (id) {
> +        mon_printf(f, " id=%s ", id);
> +    }
> +    if (dev && (!name && !id && !dev->id)) {
> +        mon_printf(f, " path=%s", dev->canonical_path);

Why not print the path for the !dev case?  I think we can just have

    mon_prinf(f, " %s:{%s", label, dev ? "dev" : "obj");
    if (dev ? dev->id : id) {
        mon_printf(f, " id=%s", dev ? dev->id : id);
    } else {
        canonical_path = object_get_canonical_path(...)
        mon_printf(f, " path=%s", canonical_path);
        g_free(canonical_path);
    }

Thanks,

Paolo

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Igor Mammedov 6 years ago
On Thu, 12 Apr 2018 11:15:04 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 29/03/2018 05:21, Alexey Kardashevskiy wrote:
> > +    DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE);
> > +    const char *id = object_property_print(obj, "id", true, NULL);  
> 
> I learnt now about commit e1ff3c67e8544f41f1bea76ba76385faee0d2bb7 and I
> find it a mistake.  The "id" is available through
> object_get_canonical_path_component.  Can you change the "id" assignment
> to use object_get_canonical_path_component instead?

object_get_canonical_path_component() should be used with care as it
assumes that object HAS parent. It will crash if parent is NULL
or hasn't been assigned yet.

Generally object doesn't need to know its own name,
we use it only for debugging and nice error reporting so far.
I'd rather have 'id' property at Object level so we won't have
to fish out ID from parent /which we aren't supposed to do and
which doesn't work in some cases/ when it's needed within
object itself.


> > +    const char *name = object_property_print(obj, "name", true, NULL);  
> 
> Who defines a name property?
> 
> > +    mon_printf(f, " %s:{", label);
> > +    if (dev) {
> > +        mon_printf(f, "dev");
> > +        if (dev->id) {
> > +            mon_printf(f, " id=%s", dev->id);
> > +        }
> > +    } else {
> > +        mon_printf(f, "obj");  
> 
> > +    }
> > +    if (name) {
> > +        mon_printf(f, " name=%s ", name);
> > +    }
> > +    if (id) {
> > +        mon_printf(f, " id=%s ", id);
> > +    }
> > +    if (dev && (!name && !id && !dev->id)) {
> > +        mon_printf(f, " path=%s", dev->canonical_path);  
> 
> Why not print the path for the !dev case?  I think we can just have
> 
>     mon_prinf(f, " %s:{%s", label, dev ? "dev" : "obj");
>     if (dev ? dev->id : id) {
>         mon_printf(f, " id=%s", dev ? dev->id : id);
>     } else {
>         canonical_path = object_get_canonical_path(...)
>         mon_printf(f, " path=%s", canonical_path);
>         g_free(canonical_path);
>     }
> 
> Thanks,
> 
> Paolo


Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Paolo Bonzini 6 years ago
On 16/04/2018 15:20, Igor Mammedov wrote:
> Generally object doesn't need to know its own name,
> we use it only for debugging and nice error reporting so far.
> I'd rather have 'id' property at Object level so we won't have
> to fish out ID from parent /which we aren't supposed to do and
> which doesn't work in some cases/ when it's needed within
> object itself.

Having an 'id' at object level is also a mess, because that id is
invalid after unparent.  Since this is just for debugging use,
object_get_canonical_path_component is the right function.  We can just
make it return NULL if there is no parent.

Paolo

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Igor Mammedov 6 years ago
On Mon, 16 Apr 2018 15:30:39 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 16/04/2018 15:20, Igor Mammedov wrote:
> > Generally object doesn't need to know its own name,
> > we use it only for debugging and nice error reporting so far.
> > I'd rather have 'id' property at Object level so we won't have
> > to fish out ID from parent /which we aren't supposed to do and
> > which doesn't work in some cases/ when it's needed within
> > object itself.  
> 
> Having an 'id' at object level is also a mess, because that id is
> invalid after unparent.
I'd just consider 'id' as object name which is valid even if there
is no parent (during whole object lifecycle).
That would allow for object to have a reachable name vs getting NULL
when parent isn't set.
Maybe Object::id is overkill, but we probably could use NamedObject
where it's needed and avoid reverse engineering id from path.
 
> Since this is just for debugging use,
> object_get_canonical_path_component is the right function.  We can just
> make it return NULL if there is no parent.
looking at current use it out-grew just debugging usecases
and it's rather messy right now:

ram_backend_memory_alloc, throttle_group_obj_complete,
xlnx_zynqmp_create_rpu, spapr_drc.c:realize, iothread_complete,
memory_region_name


> Paolo


Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Paolo Bonzini 6 years ago
On 16/04/2018 16:27, Igor Mammedov wrote:
> On Mon, 16 Apr 2018 15:30:39 +0200
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
>> On 16/04/2018 15:20, Igor Mammedov wrote:
>>> Generally object doesn't need to know its own name,
>>> we use it only for debugging and nice error reporting so far.
>>> I'd rather have 'id' property at Object level so we won't have
>>> to fish out ID from parent /which we aren't supposed to do and
>>> which doesn't work in some cases/ when it's needed within
>>> object itself.  
>>
>> Having an 'id' at object level is also a mess, because that id is
>> invalid after unparent.
> I'd just consider 'id' as object name which is valid even if there
> is no parent (during whole object lifecycle).

What's the point of an object name if it cannot be unique?

Paolo

> That would allow for object to have a reachable name vs getting NULL
> when parent isn't set.
> Maybe Object::id is overkill, but we probably could use NamedObject
> where it's needed and avoid reverse engineering id from path.
>  
>> Since this is just for debugging use,
>> object_get_canonical_path_component is the right function.  We can just
>> make it return NULL if there is no parent.
>
> looking at current use it out-grew just debugging usecases
> and it's rather messy right now:
> 
> ram_backend_memory_alloc, throttle_group_obj_complete,
> xlnx_zynqmp_create_rpu, spapr_drc.c:realize, iothread_complete,
> memory_region_name

I agree, _but_ it's definitely okay for debugging usecases.

Paolo

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Igor Mammedov 6 years ago
On Mon, 16 Apr 2018 17:29:23 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 16/04/2018 16:27, Igor Mammedov wrote:
> > On Mon, 16 Apr 2018 15:30:39 +0200
> > Paolo Bonzini <pbonzini@redhat.com> wrote:
> >   
> >> On 16/04/2018 15:20, Igor Mammedov wrote:  
> >>> Generally object doesn't need to know its own name,
> >>> we use it only for debugging and nice error reporting so far.
> >>> I'd rather have 'id' property at Object level so we won't have
> >>> to fish out ID from parent /which we aren't supposed to do and
> >>> which doesn't work in some cases/ when it's needed within
> >>> object itself.    
> >>
> >> Having an 'id' at object level is also a mess, because that id is
> >> invalid after unparent.  
> > I'd just consider 'id' as object name which is valid even if there
> > is no parent (during whole object lifecycle).  
> 
> What's the point of an object name if it cannot be unique?
It should be sufficient for it to be unique within parent's
scope and object_property_add_child() should make sure that
added object is unique within its parent's namespace.
Having named object from starters is useful as object
won't have to piggyback on parent (object_get_canonical_path_component)
when it need its own name. Then named object could use its name
freely anywhere including initfn, property setters/getters and
let object_property_add_child() take care of possible name
conflict.
From debugging/error reporting pov 'id' might be ambiguous
sometimes but it's way better than unanimous "NULL" string
or crash due to no set parent.

It sort of relates to discussion Peter started with

https://patchwork.kernel.org/patch/10224775/
"
Code that used to look like this:
    object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
    object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL);
    qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default());
can now look like this:
    sysbus_init_child(obj, "ic", &s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
" 

Considering that in most cases where named objects are used
we parent them. We might be better of with API like

named_object_new(TYPE, NAME, PARENT, ERROR)
named_object_initialize(PTR, SIZE, TYPE, NAME, PARENT, ERROR)


> Paolo
> 
> > That would allow for object to have a reachable name vs getting NULL
> > when parent isn't set.
> > Maybe Object::id is overkill, but we probably could use NamedObject
> > where it's needed and avoid reverse engineering id from path.
> >    
> >> Since this is just for debugging use,
> >> object_get_canonical_path_component is the right function.  We can just
> >> make it return NULL if there is no parent.  
> >
> > looking at current use it out-grew just debugging usecases
> > and it's rather messy right now:
> > 
> > ram_backend_memory_alloc, throttle_group_obj_complete,
> > xlnx_zynqmp_create_rpu, spapr_drc.c:realize, iothread_complete,
> > memory_region_name  
> 
> I agree, _but_ it's definitely okay for debugging usecases.
yep, since there isn't other way to do it now,
it's fine to use object_get_canonical_path_component()


> 
> Paolo


Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Paolo Bonzini 6 years ago
On 17/04/2018 14:18, Igor Mammedov wrote:
>> What's the point of an object name if it cannot be unique?
> It should be sufficient for it to be unique within parent's
> scope and object_property_add_child() should make sure that
> added object is unique within its parent's namespace.
> Having named object from starters is useful as object
> won't have to piggyback on parent (object_get_canonical_path_component)
> when it need its own name. Then named object could use its name
> freely anywhere including initfn, property setters/getters and
> let object_property_add_child() take care of possible name
> conflict.

I agree that it looks nice, but I'm worried that people forget that the
path component is only unique until object_unparent().  The use for
DEVICE_DELETED events is already a bad thing...

Paolo

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Markus Armbruster 6 years ago
Paolo Bonzini <pbonzini@redhat.com> writes:

> On 17/04/2018 14:18, Igor Mammedov wrote:
>>> What's the point of an object name if it cannot be unique?
>> It should be sufficient for it to be unique within parent's
>> scope and object_property_add_child() should make sure that
>> added object is unique within its parent's namespace.
>> Having named object from starters is useful as object
>> won't have to piggyback on parent (object_get_canonical_path_component)
>> when it need its own name. Then named object could use its name
>> freely anywhere including initfn, property setters/getters and
>> let object_property_add_child() take care of possible name
>> conflict.
>
> I agree that it looks nice, but I'm worried that people forget that the
> path component is only unique until object_unparent().  The use for
> DEVICE_DELETED events is already a bad thing...

Hmm.  If the canonical QOM path isn't the proper way to identify a
device in QMP, what else is?  Honest question!

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Paolo Bonzini 6 years ago
On 18/04/2018 08:32, Markus Armbruster wrote:
> Paolo Bonzini <pbonzini@redhat.com> writes:
> 
>> On 17/04/2018 14:18, Igor Mammedov wrote:
>>>> What's the point of an object name if it cannot be unique?
>>> It should be sufficient for it to be unique within parent's
>>> scope and object_property_add_child() should make sure that
>>> added object is unique within its parent's namespace.
>>> Having named object from starters is useful as object
>>> won't have to piggyback on parent (object_get_canonical_path_component)
>>> when it need its own name. Then named object could use its name
>>> freely anywhere including initfn, property setters/getters and
>>> let object_property_add_child() take care of possible name
>>> conflict.
>>
>> I agree that it looks nice, but I'm worried that people forget that the
>> path component is only unique until object_unparent().  The use for
>> DEVICE_DELETED events is already a bad thing...
> 
> Hmm.  If the canonical QOM path isn't the proper way to identify a
> device in QMP, what else is?  Honest question!

The canonical path is; the last component alone is not.

Paolo

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Alexey Kardashevskiy 6 years ago
On 12/4/18 7:15 pm, Paolo Bonzini wrote:
> On 29/03/2018 05:21, Alexey Kardashevskiy wrote:
>> +    DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE);
>> +    const char *id = object_property_print(obj, "id", true, NULL);
> 
> I learnt now about commit e1ff3c67e8544f41f1bea76ba76385faee0d2bb7 and I
> find it a mistake.  The "id" is available through
> object_get_canonical_path_component.  Can you change the "id" assignment
> to use object_get_canonical_path_component instead?

Uff. I did some tests and found that this is needed, at least. I can also
returning NULL from object_get_canonical_path_component(), it just seems to
be a real case and majority of object_get_canonical_path_component() users
do not test the returned pointer.

===================
diff --git a/qom/object.c b/qom/object.c
index 4677951..0c2d5c2 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1645,7 +1645,9 @@ gchar *object_get_canonical_path_component(Object *obj)
     GHashTableIter iter;

     g_assert(obj);
-    g_assert(obj->parent != NULL);
+    if (!obj->parent) {
+        return g_strdup("<no-parent>");
+    }

     g_hash_table_iter_init(&iter, obj->parent->properties);
     while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
@@ -1668,7 +1670,7 @@ gchar *object_get_canonical_path(Object *obj)
     Object *root = object_get_root();
     char *newpath, *path = NULL;

-    while (obj != root) {
+    while (obj && obj != root) {
         char *component = object_get_canonical_path_component(obj);

         if (path) {
@@ -1681,6 +1683,8 @@ gchar *object_get_canonical_path(Object *obj)
         }

         obj = obj->parent;
+        if (!obj)
+            printf("+++Q+++ (%u) %s %u\n", getpid(), __func__, __LINE__);
     }

====================


as QMP crashes QEMU with this:

{"execute": "qom-get", "arguments": {"path":
"/machine/unattached/device[3]/smram[0]", "property": "container"}}

with the patch it returns:

{'return': '/<no-parent>/mem-container-smram[0]'}


Without the patch it crashes as:

(gdb) bt
#0  object_get_canonical_path (obj=0x0) at /home/aik/p/qemu/qom/object.c:1687
#1  0x0000555555829676 in memory_region_get_container (obj=0x555556d5c6e0,
v=0x555557a7c530, name=0x5555569a4fe0 "container", opaque=0x0,
errp=0x7fffffffda58) at /home/aik/p/qemu/memory.c:1172
#2  0x0000555555bf719a in object_property_get (obj=0x555556d5c6e0,
v=0x555557a7c530, name=0x5555569a4fe0 "container", errp=0x7fffffffda58) at
/home/aik/p/qemu/qom/object.c:1107
#3  0x0000555555bfa2de in object_property_get_qobject (obj=0x555556d5c6e0,
name=0x5555569a4fe0 "container", errp=0x7fffffffdae8) at
/home/aik/p/qemu/qom/qom-qobject.c:39
#4  0x00005555559963cf in qmp_qom_get (path=0x5555576e5680
"/machine/unattached/device[3]/smram[0]", property=0x5555569a4fe0
"container", errp=0x7fffffffdae8) at /home/aik/p/qemu/qmp.c:271
#5  0x000055555598de6c in qmp_marshal_qom_get (args=0x5555573b5720,
ret=0x7fffffffdb60, errp=0x7fffffffdb58) at qapi/qapi-commands-misc.c:1249
#6  0x0000555555d155ad in do_qmp_dispatch (cmds=0x55555645a3e0
<qmp_commands>, request=0x5555573aff80, errp=0x7fffffffdbb0) at
/home/aik/p/qemu/qapi/qmp-dispatch.c:111
#7  0x0000555555d1576d in qmp_dispatch (cmds=0x55555645a3e0 <qmp_commands>,
request=0x5555573aff80) at /home/aik/p/qemu/qapi/qmp-dispatch.c:160
#8  0x0000555555819361 in monitor_qmp_dispatch_one (req_obj=0x555556fd7ee0)
at /home/aik/p/qemu/monitor.c:4091
#9  0x0000555555819573 in monitor_qmp_bh_dispatcher (data=0x0) at
/home/aik/p/qemu/monitor.c:4149
#10 0x0000555555d23df9 in aio_bh_call (bh=0x555556a1a650) at
/home/aik/p/qemu/util/async.c:90
#11 0x0000555555d23e91 in aio_bh_poll (ctx=0x5555569f0ce0) at
/home/aik/p/qemu/util/async.c:118
#12 0x0000555555d28a92 in aio_dispatch (ctx=0x5555569f0ce0) at
/home/aik/p/qemu/util/aio-posix.c:436
#13 0x0000555555d2422c in aio_ctx_dispatch (source=0x5555569f0ce0,
callback=0x0, user_data=0x0) at /home/aik/p/qemu/util/async.c:261
#14 0x00007ffff4cc6b77 in ?? ()
#15 0x0000000000000000 in ?? ()


It is fc27/x86_64 both host and guest, QMP issues when guest booted to the
login prompt (so I'd not expect any hotplugs) and I have no idea what smram
is and what its parent should be.


>> +    const char *name = object_property_print(obj, "name", true, NULL);
> 
> Who defines a name property?

Nothing, not sure why I put it here in the first place, will remove.

> 
>> +    mon_printf(f, " %s:{", label);
>> +    if (dev) {
>> +        mon_printf(f, "dev");
>> +        if (dev->id) {
>> +            mon_printf(f, " id=%s", dev->id);
>> +        }
>> +    } else {
>> +        mon_printf(f, "obj");
> 
>> +    }
>> +    if (name) {
>> +        mon_printf(f, " name=%s ", name);
>> +    }
>> +    if (id) {
>> +        mon_printf(f, " id=%s ", id);
>> +    }
>> +    if (dev && (!name && !id && !dev->id)) {
>> +        mon_printf(f, " path=%s", dev->canonical_path);
> 
> Why not print the path for the !dev case?  I think we can just have
> 
>     mon_prinf(f, " %s:{%s", label, dev ? "dev" : "obj");
>     if (dev ? dev->id : id) {
>         mon_printf(f, " id=%s", dev ? dev->id : id);
>     } else {
>         canonical_path = object_get_canonical_path(...)
>         mon_printf(f, " path=%s", canonical_path);
>         g_free(canonical_path);
>     }

Makes sense, assuming the issue above is fixed.


> 
> Thanks,
> 
> Paolo
> 


-- 
Alexey

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Paolo Bonzini 6 years ago
On 19/04/2018 04:41, Alexey Kardashevskiy wrote:
> it just seems to
> be a real case and majority of object_get_canonical_path_component() users
> do not test the returned pointer.
> 
> ===================
> diff --git a/qom/object.c b/qom/object.c
> index 4677951..0c2d5c2 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -1645,7 +1645,9 @@ gchar *object_get_canonical_path_component(Object *obj)
>      GHashTableIter iter;
> 
>      g_assert(obj);
> -    g_assert(obj->parent != NULL);

I agree but why wouldn't the caller have crashed anyway on this assertion?

> as QMP crashes QEMU with this:
> 
> {"execute": "qom-get", "arguments": {"path":
> "/machine/unattached/device[3]/smram[0]", "property": "container"}}
> 
> with the patch it returns:
> 
> {'return': '/<no-parent>/mem-container-smram[0]'}

The root cause of this is that the accelerator object is not added to
the QOM object tree.

Paolo

Re: [Qemu-devel] [PATCH qemu] RFC: memory/hmp: Print owners/parents in "info mtree"
Posted by Alexey Kardashevskiy 6 years ago
On 19/4/18 8:33 pm, Paolo Bonzini wrote:
> On 19/04/2018 04:41, Alexey Kardashevskiy wrote:
>> it just seems to
>> be a real case and majority of object_get_canonical_path_component() users
>> do not test the returned pointer.
>>
>> ===================
>> diff --git a/qom/object.c b/qom/object.c
>> index 4677951..0c2d5c2 100644
>> --- a/qom/object.c
>> +++ b/qom/object.c
>> @@ -1645,7 +1645,9 @@ gchar *object_get_canonical_path_component(Object *obj)
>>      GHashTableIter iter;
>>
>>      g_assert(obj);
>> -    g_assert(obj->parent != NULL);
> 
> I agree but why wouldn't the caller have crashed anyway on this assertion?


Not sure I am following. It did crash, this is why I replaced the assert to
make qom-get working.


>> as QMP crashes QEMU with this:
>>
>> {"execute": "qom-get", "arguments": {"path":
>> "/machine/unattached/device[3]/smram[0]", "property": "container"}}
>>
>> with the patch it returns:
>>
>> {'return': '/<no-parent>/mem-container-smram[0]'}
> 
> The root cause of this is that the accelerator object is not added to
> the QOM object tree.

ookay.


-- 
Alexey