]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: support multiple instances of the same probe in a function
authorKris Van Hees <kris.van.hees@oracle.com>
Thu, 28 Jan 2016 02:36:01 +0000 (21:36 -0500)
committerKris Van Hees <kris.van.hees@oracle.com>
Sat, 30 Jan 2016 09:55:12 +0000 (04:55 -0500)
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 <kris.van.hees@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
kernel/dtrace/dtrace_sdt_core.c
scripts/dtrace_sdt.sh

index 5e4f189df1572c03a5c06b88fbcf8b0f22519df5..0a93aac1e032420eb5aef15c56e9ad272ad275db 100644 (file)
@@ -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
index 1fce667026ca00e3aaa054db5e0664af144796e7..528121243651d0fa0f1fa2ef3905d671ac6360d7 100755 (executable)
@@ -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;
         }