From: Kris Van Hees Date: Thu, 28 Jan 2016 02:36:01 +0000 (-0500) Subject: dtrace: support multiple instances of the same probe in a function X-Git-Tag: v4.1.12-92~204^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=161dad5cda797f8e01cf43923524df63809b3990;p=users%2Fjedix%2Flinux-maple.git dtrace: support multiple instances of the same probe in a function Up until now, no function in the kernel (or modules) ever had more than a single instance of the same probe in a single function. Due to compiler optimizations, sparc64 caused duplication of a probe call in kernel code. The existing code was not adequate to deal wih that situation, causing the probe to not get enabled in more than one location, thereby causing it to not fire when expected. This commit adds support to dtrace_sdt.sh to handle multiple instances of the same probe in a single function. It also adds equialent support in the SDT boot-time processing to ensure that probes with multiple locations in a function are linked together so that all locations are enabled and disabled together. (While this was found as an artifact of testing the 4.3 kernel series, it also applies to 4.1 because it is not unlikely that a compiler upgrade may cause the same problem there.) Orabug: 22514493 Signed-off-by: Kris Van Hees Acked-by: Nick Alcock --- diff --git a/kernel/dtrace/dtrace_sdt_core.c b/kernel/dtrace/dtrace_sdt_core.c index 5e4f189df157..0a93aac1e032 100644 --- a/kernel/dtrace/dtrace_sdt_core.c +++ b/kernel/dtrace/dtrace_sdt_core.c @@ -20,7 +20,8 @@ const char *sdt_prefix = "__dtrace_probe_"; static int sdt_probe_set(sdt_probedesc_t *sdp, char *name, char *func, - uintptr_t addr, asm_instr_t **paddr) + uintptr_t addr, asm_instr_t **paddr,\ + sdt_probedesc_t *prv) { if ((sdp->sdpd_name = kstrdup(name, GFP_KERNEL)) == NULL) { kfree(sdp); @@ -34,9 +35,14 @@ static int sdt_probe_set(sdt_probedesc_t *sdp, char *name, char *func, } sdp->sdpd_offset = addr; + sdp->sdpd_next = NULL; *paddr = (asm_instr_t *)addr; + if (prv && strcmp(prv->sdpd_name, sdp->sdpd_name) == 0 + && strcmp(prv->sdpd_func, sdp->sdpd_func) == 0) + prv->sdpd_next = sdp; + return 0; } @@ -96,7 +102,8 @@ void dtrace_sdt_register(struct module *mp) char *func = pi->name + pi->name_len + 1; if (sdt_probe_set(&sdps[cnt], pi->name, func, pi->addr, - &addrs[cnt])) + &addrs[cnt], + cnt > 0 ? &sdps[cnt - 1] : NULL)) pr_warning("%s: failed to add SDT probe %s\n", __func__, pi->name); else diff --git a/scripts/dtrace_sdt.sh b/scripts/dtrace_sdt.sh index 1fce667026ca..528121243651 100755 --- a/scripts/dtrace_sdt.sh +++ b/scripts/dtrace_sdt.sh @@ -197,28 +197,32 @@ fi for (i = 1; i <= NF; i++) { prb = $i; - pn = fun":"prb; - ad = addl(baseaddr, poffst[pn]); - - if (arch == "x86" || arch == "x86_64") - ad = subl(ad, 1); - - if (lfn != "kmod") { - printf "\tPTR\t0x%s\n", ad; - printf "\tPTR\t%d\n", length(prb); - printf "\tPTR\t%d\n", length(fun); - printf "\t.asciz\t\042%s\042\n", prb; - printf "\t.asciz\t\042%s\042\n", fun; - print "\tALGN"; - } else { - if (probec == 0) - print "static sdt_probedesc_t\t_sdt_probes[] = {"; + pn = fun ":" prb; + + for (j = 0; j < pidcnt[pn]; j++) { + pid = pn"-"j; + ad = addl(baseaddr, poffst[pid]); + + if (arch == "x86" || arch == "x86_64") + ad = subl(ad, 1); + + if (lfn != "kmod") { + printf "\tPTR\t0x%s\n", ad; + printf "\tPTR\t%d\n", length(prb); + printf "\tPTR\t%d\n", length(fun); + printf "\t.asciz\t\042%s\042\n", prb; + printf "\t.asciz\t\042%s\042\n", fun; + print "\tALGN"; + } else { + if (probec == 0) + print "static sdt_probedesc_t\t_sdt_probes[] = {"; + + printf " {\042%s\042, \042%s\042, 0x%s },\n", \ + prb, fun, ad; + } - printf " {\042%s\042, \042%s\042, 0x%s },\n", \ - prb, fun, ad; + probec++; } - - probec++; } } @@ -238,8 +242,12 @@ fi sub(/^0+/, "", $2); pn = fun":"$4; - probes[fun] = $4 " " probes[fun]; - poffst[pn] = subl($2, addr); + if (!pidcnt[pn]) + probes[fun] = $4 " " probes[fun]; + + pid = pn"-"int(pidcnt[pn]); + pidcnt[pn]++; + poffst[pid] = subl($2, addr); next; }