Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
dyndbg: RFC add debug-trace callback, selftest with it. RFC
Sean Paul seanpaul@chromium.org proposed, in https://patchwork.freedesktop.org/series/78133/ drm/trace: Mirror DRM debug logs to tracefs That patchset's objective is to be able to independently steer some of the debug stream to an alternate tracing destination, by splitting drm_debug_enabled() into syslog & trace flavors, and enabling them separately with a drm.debug_trace knob. 2 advantages are identified: - syslog is heavyweight, alternate stream is lighter - steering selected categories separately means less traffic Dynamic-Debug can do this better: 1- all work is behind jump-label's NOOP, Zero overhead when off. 2- perfect site selectivity, no unwanted traffic. drm's debug categories are a general classification system, not one tailored to pick out the exact pool of pr_debugs to watch/trace. With drm.debug built on dyndbg, the given "drm:<cat>:" system can be used to select a base trace-set, which can then be adjusted +/-, and/or augmented with unrelated pr_debugs that just happen to be useful. And this tweaking can be done at the command-line, and reduced to a script. Then the string-prefix "drm:<cat>:" system can be extended to suit. The basic elements: - add a new struct _ddebug member: (*tracer)(char *format, ...) - add a new T flag to enable tracer - adjust the static-key-enable/disable condition for (p|T) - if (p) before printk, since T enables too. - if (T) call tracer if its true = int dynamic_debug_register_tracer(query, modname, tracer); = int dynamic_debug_unregister_tracer(query, modname, cookie); This new interface lets clients set/unset a tracer function on each callsite matching the query, for example: "drm:atomic:fail:". Clients must unregister the same callsites they register, allowing protection of each client's dyndbg-state setup against overwrites by others, while allowing maximal sharing of 1 slot/callsite. The internal call-chain gets some rework: it gets new void* tracer param, which dynamic_debug_exec_queries() hides from public. And convert ddebug_exec_queries() to wrap __ddebug_exec_queries(), and move the query copy code to it. public: passing down: dynamic_debug_(un)register_tracer tracer dynamic_debug_exec_queries tracer=NULL calling: ddebug_exec_queries copies ro-query, tracer __ddebug_exec_queries modifies query, tracer ddebug_exec_query modifies query, tracer Then adjust most ddebug_exec_queries users to __ddebug_exec_queries Intended Behavior: (things are in flux, RFC) - register sets empty slot, doesn't overwrite the query selects callsites, and sets +T (grammar requires +-action) - register allows same-tracer over-set wo warn 2nd register can then enable superset, subset, disjoint set - unregister clears slot if it matches cookie/tracer query selects set, -T (as tested) tolerates over-clears - dd-exec-queries(+/-T) can modify the enablements not sure its needed, but it falls out.. The code is currently in-line in ddebug_change(), to be moved to separate fn, rc determines flow, may also veto/alter changes by altering flag-settings - tbd. TBD: Im not sure what happens when exec-queries(+T) hits a site wo a tracer (silence I think. maybe not ideal). SELFTEST: test_dynamic_debug.ko: Uses the tracer facility to implement a selftest: - DUT(x) calls a set of categorized pr_debugs x times - A custom tracer counts the number of calls (of T-enabled pr_debugs), - test registers the tracer on the function, then iteratively: manipulates dyndbg states via query-cmds calls DUT(x) counts enabled callsite executions reports mismatches - modprobe test_dynamic_debug broken_tracer=1 attaches a broken tracer: recursive on pr_debug Bad Things Happen. has thrown me interesting panics. This needs more work. RFC. waste of time due to use_bad_tracer properties ? NOTES: Next step: replace tracer member with a hashtable lookup, done only when T. Registration then becomes populating the hashtable; mod->name would make a good key, which would limit tracer mapping granularity to 1 registrant per module, but not enablement, which is still the per-callsite bit. ERRORS (or WARNINGS): It should be an error to +T a callsite which has no aux_print set (ie already registered with a query that selected that callsite). This tacitly enforces registration. Then +T,-T can toggle those aux_print callsites (or subsets of them) to tailor the debug-stream for the purpose. Controlling flow is the best work limiter. Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
- Loading branch information