[PATCH 2/3] dyndbg: zhandle+1 plus info tweaks, BUG_ONs
Jim Cromie
jim.cromie at gmail.com
Sat Jul 25 12:36:01 EDT 2020
In preparation for union between zhandle and callsite, add a +1 offset
to zhandle as its created & stored, and a corresponding -1 in the
get/put helper funcs which access it.
With the +1, the value cannot work as a pointer, so we'll get early
detonation if the union goes poorly. This relys on the 'fact' uhm
observation that zhandles were always even numbered. So far so good.
Also add BUG-ONs to track/assert invariants into ddebug_zpool_init
and the get/put inline helpers, and several debug prints.
Signed-off-by: Jim Cromie <jim.cromie at gmail.com>
---
lib/dynamic_debug.c | 72 +++++++++++++++++++++++++++++++--------------
1 file changed, 50 insertions(+), 22 deletions(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index bb23d5d56116..96252ffacb77 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -145,13 +145,15 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
static inline struct _ddebug* ddebug_zrec_get(long unsigned int handle)
{
+ BUG_ON(!(handle % 2)); /* distinct from pointer */
return (struct _ddebug*)
- zs_map_object(dd_callsite_zpool, handle, ZS_MM_RW);
+ zs_map_object(dd_callsite_zpool, handle - 1, ZS_MM_RW);
}
static inline void ddebug_zrec_put(long unsigned int handle)
{
- zs_unmap_object(dd_callsite_zpool, handle);
+ BUG_ON(!(handle % 2)); /* distinct from pointer */
+ zs_unmap_object(dd_callsite_zpool, handle - 1);
}
/*
@@ -587,22 +589,31 @@ static int remaining(int wrote)
return 0;
}
-static char *dynamic_emit_prefix(const struct _ddebug *dp, char *buf)
+static char *dynamic_emit_prefix( struct _ddebug *dp, char *buf)
{
int pos_after_tid;
int pos = 0;
- struct _ddebug *desc;
+ struct _ddebug *desc = dp; /* updated if zhandle */
*buf = '\0';
+ BUG_ON(dp->zhandle == 1);
+
if (!dp->zhandle) {
- pr_err("Nul zhandle: %s.%s\n", dp->modname, dp->function);
- desc = dp;
- } else {
+ /* without union, happens until late-init */
+ pr_err("nul zhandle: %s.%s\n", dp->modname, dp->function);
+ } else if (dp->zhandle % 2) {
+ /* normal ops, after zpool filled
+ zhandle is odd to distinguish from pointer
+ */
desc = ddebug_zrec_get(dp->zhandle);
- v3pr_info("good zhandle: %s.%s\n",
+ v3pr_info("get zhandle: %s.%s\n",
desc->modname, desc->function);
- }
+ } else
+ /* with union, happens until late-init */
+ pr_err("some transitional state: %s.%s %lu\n",
+ desc->modname, desc->function, dp->zhandle);
+
if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
@@ -627,9 +638,9 @@ static char *dynamic_emit_prefix(const struct _ddebug *dp, char *buf)
buf[PREFIX_SIZE - 1] = '\0';
if (!dp->zhandle) {
- pr_err("Nul zhandle\n");
- } else {
- v3pr_info("got zhandle\n");
+ pr_err("Nul zhandle: %s.%s\n", desc->modname, desc->function);
+ } else if (dp->zhandle % 2) {
+ v2pr_info("put zhandle: %s.%s\n", desc->modname, desc->function);
ddebug_zrec_put(dp->zhandle);
}
@@ -898,7 +909,6 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
struct ddebug_iter *iter = m->private;
struct _ddebug *dp = p;
struct flagsbuf flags;
- long unsigned int handle;
if (p == SEQ_START_TOKEN) {
seq_puts(m,
@@ -906,16 +916,19 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
return 0;
}
- BUG_ON(!dp->zhandle);
- handle = dp->zhandle;
+ BUG_ON(!dp->zhandle); /* must be set by now */
- dp = ddebug_zrec_get(handle);
+ if (dp->zhandle == 1)
+ vpr_info("dp:%p mapping ?? h:%lu %s.%s\n", dp, dp->zhandle,
+ iter->table->mod_name, dp->function);
+
+ dp = ddebug_zrec_get(dp->zhandle);
if (!dp) {
- pr_err("zs-map failed on %lu\n", handle);
+ pr_err("zs-map failed on %lu\n", dp->zhandle);
return 0; // bail
}
- v3pr_info("mapped h:%lu %s\n", handle, dp->function);
+ v3pr_info("mapped h:%lu %s\n", dp->zhandle, dp->function);
seq_printf(m, "%s:%u [%s]%s =%s \"",
trim_prefix(dp->filename), dp->lineno,
@@ -924,7 +937,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_escape(m, dp->format, "\t\r\n\"");
seq_puts(m, "\"\n");
- ddebug_zrec_put(handle);
+ ddebug_zrec_put(dp->zhandle);
return 0;
}
@@ -935,6 +948,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
*/
static void ddebug_proc_stop(struct seq_file *m, void *p)
{
+ vpr_info("called\n");
mutex_unlock(&ddebug_lock);
}
@@ -947,7 +961,6 @@ static const struct seq_operations ddebug_proc_seqops = {
static int ddebug_proc_open(struct inode *inode, struct file *file)
{
- vpr_info("called\n");
return seq_open_private(file, &ddebug_proc_seqops,
sizeof(struct ddebug_iter));
}
@@ -972,7 +985,7 @@ static const struct proc_ops proc_fops = {
/*
* copy struct _ddebug records into the zpool, and remember zhandle in
* the struct. This is close to what we'll want to unionize the
- * handle and the struct
+ * handle and the struct.
*/
static void ddebug_zpool_add(struct _ddebug *dp)
{
@@ -985,7 +998,21 @@ static void ddebug_zpool_add(struct _ddebug *dp)
pr_err("pool malloc failed on %s\n", dp->function);
return;
}
- dp->zhandle = handle;
+
+ /* We want !!is_odd(zhandle), to insure crash if used as a
+ pointer. Then we can test the unionized value to see if
+ its a pointer or a zhandle to a zrec. Observation shows
+ handle is always even, and the BUG_ON confirms, so
+ ++zhandle gives us our testable condition.
+ */
+ BUG_ON(handle % 2);
+
+ /* update zhandle in kmem record before copy to zrec, so its
+ in both places, to avoid use-after-restore inconsistencies.
+ This will break once we unionize (the zrec), hopefully all
+ these comments will help sort it all out.
+ */
+ dp->zhandle = handle + 1;
cursor = (struct _ddebug *)
zs_map_object(dd_callsite_zpool, handle, ZS_MM_WO);
@@ -999,6 +1026,7 @@ static void ddebug_zpool_add(struct _ddebug *dp)
v3pr_info("h:%lu %s\n", handle, cursor->function);
zs_unmap_object(dd_callsite_zpool, handle);
+
}
/*
--
2.26.2
More information about the Kernelnewbies
mailing list