]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: Various memory allocation fixes (leaks, footprint reduction, ...)
authorKris Van Hees <kris.van.hees@oracle.com>
Fri, 20 Sep 2013 13:53:05 +0000 (09:53 -0400)
committerKris Van Hees <kris.van.hees@oracle.com>
Fri, 20 Sep 2013 13:58:31 +0000 (09:58 -0400)
Orabug: 17488207

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
15 files changed:
dtrace/dtrace_actdesc.c
dtrace/dtrace_dev.c
dtrace/dtrace_dif.c
dtrace/dtrace_dof.c
dtrace/dtrace_ecb.c
dtrace/dtrace_enable.c
dtrace/dtrace_hash.c
dtrace/dtrace_predicate.c
dtrace/dtrace_probe.c
dtrace/dtrace_ptofapi.c
dtrace/fasttrap_dev.c
dtrace/include/dtrace/dtrace_impl.h
dtrace/profile_dev.c
dtrace/sdt_dev.c
dtrace/systrace_dev.c

index 86f66a2131de8a90f9ebbd13d8704c4b1a223e71..be58b37a55a4987f3776a0153a47a190d23395a2 100644 (file)
@@ -44,7 +44,7 @@ dtrace_actdesc_t *dtrace_actdesc_create(dtrace_actkind_t kind, uint32_t ntuple,
               (arg == 0 && kind == DTRACEACT_PRINTA));
 #endif
 
-       act = vzalloc(sizeof (dtrace_actdesc_t));
+       act = kzalloc(sizeof (dtrace_actdesc_t), GFP_KERNEL);
        if (act == NULL)
                return NULL;
 
@@ -92,5 +92,5 @@ void dtrace_actdesc_release(dtrace_actdesc_t *act, dtrace_vstate_t *vstate)
                        vfree(str);
        }
 
-       vfree(act);
+       kfree(act);
 }
index 853a3ef720121b100c79697453c5ed12cd2e4257..e4d5da6f4f928e975fa4b0a48c427465ba93e326 100644 (file)
@@ -490,6 +490,7 @@ static long dtrace_ioctl(struct file *file,
 
        case DTRACEIOC_PROBEMATCH:
        case DTRACEIOC_PROBES: {
+               int                     id;
                dtrace_probe_t          *probe = NULL;
                dtrace_probedesc_t      desc;
                dtrace_probekey_t       pkey;
@@ -528,16 +529,17 @@ static long dtrace_ioctl(struct file *file,
 
                mutex_lock(&dtrace_lock);
 
+               id = desc.dtpd_id;
                if (cmd == DTRACEIOC_PROBEMATCH)  {
                        int     m = 0;
 
-                       while ((probe = dtrace_probe_get_next(desc.dtpd_id))
+                       while ((probe = dtrace_probe_get_next(&id))
                               != NULL) {
                                if ((m = dtrace_match_probe(
                                                probe, &pkey, priv, uid)))
                                        break;
 
-                               desc.dtpd_id = probe->dtpr_id + 1;
+                               id++;
                        }
 
                        if (m < 0) {
@@ -545,12 +547,12 @@ static long dtrace_ioctl(struct file *file,
                                return -EINVAL;
                        }
                } else {
-                       while ((probe = dtrace_probe_get_next(desc.dtpd_id))
+                       while ((probe = dtrace_probe_get_next(&id))
                               != NULL) {
                                if (dtrace_match_priv(probe, priv, uid))
                                        break;
 
-                               desc.dtpd_id = probe->dtpr_id + 1;
+                               id++;
                        }
                }
 
@@ -1361,6 +1363,17 @@ int dtrace_dev_init(void)
        mutex_lock(&dtrace_provider_lock);
        mutex_lock(&dtrace_lock);
 
+       rc = dtrace_probe_init();
+       if (rc) {
+               pr_err("Failed to initialize DTrace core\n");
+
+               mutex_unlock(&cpu_lock);
+               mutex_unlock(&dtrace_provider_lock);
+               mutex_unlock(&dtrace_lock);
+
+               return rc;
+       }
+
        /*
         * Register the device for the DTrace core.
         */
@@ -1407,8 +1420,6 @@ int dtrace_dev_init(void)
        register_cpu_setup_func((cpu_setup_func_t *)dtrace_cpu_setup, NULL);
 #endif
 
-       dtrace_probe_init();
-
 #ifdef FIXME
        dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, 1, INT_MAX,
                                    0);
index e2fa3365d481b54856d768b6f5269e5bddc33338..d6339a8dc558d9618e128e2a2ec37d5a0b20aeb0 100644 (file)
@@ -923,7 +923,7 @@ void dtrace_difo_init(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
                }
 
                if ((svar = (*svarp)[id]) == NULL) {
-                       svar = vzalloc(sizeof(dtrace_statvar_t));
+                       svar = kzalloc(sizeof(dtrace_statvar_t), GFP_KERNEL);
                        svar->dtsv_var = *v;
 
                        if ((svar->dtsv_size = dsize) != 0) {
@@ -950,7 +950,7 @@ dtrace_difo_t * dtrace_difo_duplicate(dtrace_difo_t *dp,
        ASSERT(dp->dtdo_buf != NULL);
        ASSERT(dp->dtdo_refcnt != 0);
 
-       new = vzalloc(sizeof(dtrace_difo_t));
+       new = kzalloc(sizeof(dtrace_difo_t), GFP_KERNEL);
 
        ASSERT(dp->dtdo_buf != NULL);
        sz = dp->dtdo_len * sizeof(dif_instr_t);
@@ -1035,7 +1035,7 @@ void dtrace_difo_destroy(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
                        vfree((void *)(uintptr_t)svar->dtsv_data);
                }
 
-               vfree(svar);
+               kfree(svar);
                svarp[id] = NULL;
        }
 
@@ -1043,7 +1043,7 @@ void dtrace_difo_destroy(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
         vfree(dp->dtdo_inttab);
         vfree(dp->dtdo_strtab);
         vfree(dp->dtdo_vartab);
-        vfree(dp);
+        kfree(dp);
 }
 
 void dtrace_difo_release(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
index 179c65f28d52a974ae45c86e17f912b21222c3bb..08a2e43639a02099032fcf0060cf4d399d3ad8c2 100644 (file)
@@ -424,7 +424,7 @@ static dtrace_difo_t *dtrace_dof_difo(dof_hdr_t *dof, dof_sec_t *sec,
        dofd = (dof_difohdr_t *)(uintptr_t)(daddr + sec->dofs_offset);
        n = (sec->dofs_size - sizeof(*dofd)) / sizeof(dof_secidx_t) + 1;
 
-       dp = vzalloc(sizeof(dtrace_difo_t));
+       dp = kzalloc(sizeof(dtrace_difo_t), GFP_KERNEL);
        if (dp == NULL) {
                dtrace_dof_error(dof, "out-of-memory");
                return NULL;
@@ -555,7 +555,7 @@ err:
        if (dp->dtdo_vartab != NULL)
                vfree(dp->dtdo_vartab);
 
-       vfree(dp);
+       kfree(dp);
 
        return NULL;
 }
@@ -735,7 +735,7 @@ static dtrace_ecbdesc_t *dtrace_dof_ecbdesc(dof_hdr_t *dof, dof_sec_t *sec,
        if (sec == NULL)
                return NULL;
 
-       ep = vzalloc(sizeof(dtrace_ecbdesc_t));
+       ep = kzalloc(sizeof(dtrace_ecbdesc_t), GFP_KERNEL);
        if (ep == NULL)
                return NULL;
        ep->dted_uarg = ecb->dofe_uarg;
@@ -771,7 +771,7 @@ static dtrace_ecbdesc_t *dtrace_dof_ecbdesc(dof_hdr_t *dof, dof_sec_t *sec,
 err:
        if (pred != NULL)
                dtrace_predicate_release(pred, vstate);
-       vfree(ep);
+       kfree(ep);
        return NULL;
 }
 
@@ -1146,14 +1146,14 @@ static dtrace_helpers_t *dtrace_helpers_create(struct task_struct *curr)
        ASSERT(MUTEX_HELD(&dtrace_lock));
        ASSERT(curr->dtrace_helpers == NULL);
 
-       dth = vzalloc(sizeof(dtrace_helpers_t));
+       dth = kzalloc(sizeof(dtrace_helpers_t), GFP_KERNEL);
        if (dth == NULL)
                return NULL;
 
        dth->dthps_actions = vzalloc(sizeof(dtrace_helper_action_t *) *
                                     DTRACE_NHELPER_ACTIONS);
        if (dth->dthps_actions == NULL) {
-               vfree(dth);
+               kfree(dth);
                return NULL;
        }
 
@@ -1416,7 +1416,7 @@ static void dtrace_helper_action_destroy(dtrace_helper_action_t *helper,
        }
 
        vfree(helper->dtha_actions);
-       vfree(helper);
+       kfree(helper);
 }
 
 static int dtrace_helper_action_add(int which, dtrace_ecbdesc_t *ep)
@@ -1448,7 +1448,7 @@ static int dtrace_helper_action_add(int which, dtrace_ecbdesc_t *ep)
        if (count >= dtrace_helper_actions_max)
                return -ENOSPC;
 
-       helper = vzalloc(sizeof(dtrace_helper_action_t));
+       helper = kzalloc(sizeof(dtrace_helper_action_t), GFP_KERNEL);
        if (helper == NULL)
                return -ENOMEM;
 
@@ -1532,7 +1532,7 @@ static int dtrace_helper_provider_add(dof_helper_t *dofhp, int gen)
                        return -EALREADY;
        }
 
-       hprov = vzalloc(sizeof(dtrace_helper_provider_t));
+       hprov = kzalloc(sizeof(dtrace_helper_provider_t), GFP_KERNEL);
        if (hprov == NULL)
                return -ENOMEM;
        hprov->dthp_prov = *dofhp;
@@ -1559,7 +1559,7 @@ static int dtrace_helper_provider_add(dof_helper_t *dofhp, int gen)
                dth->dthps_provs = vzalloc(dth->dthps_maxprovs *
                                           sizeof(dtrace_helper_provider_t *));
                if (dth->dthps_provs == NULL) {
-                       vfree(hprov);
+                       kfree(hprov);
                        return -ENOMEM;
                }
 
@@ -1588,7 +1588,7 @@ static void dtrace_helper_provider_destroy(dtrace_helper_provider_t *hprov)
 
                dof = (dof_hdr_t *)(uintptr_t)hprov->dthp_prov.dofhp_dof;
                dtrace_dof_destroy(dof);
-               vfree(hprov);
+               kfree(hprov);
        } else
                mutex_unlock(&dtrace_lock);
 }
@@ -1876,6 +1876,11 @@ int dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp)
                return -1;
        }
 
+       dt_dbg_dof("DOF 0x%p from helper {'%s', %p, %p}...\n",
+                  dof, dhp ? dhp->dofhp_mod : "<none>",
+                       dhp ? dhp->dofhp_addr : NULL,
+                       dhp ? dhp->dofhp_dof : NULL);
+
        vstate = &dth->dthps_vstate;
 
        if ((rv = dtrace_dof_slurp(dof, vstate, NULL, &enab,
@@ -2053,7 +2058,7 @@ void dtrace_helpers_destroy(struct task_struct *tsk)
 
        dtrace_vstate_fini(&help->dthps_vstate);
        vfree(help->dthps_actions);
-       vfree(help);
+       kfree(help);
 
        --dtrace_helpers;
        mutex_unlock(&dtrace_lock);
@@ -2088,7 +2093,8 @@ void dtrace_helpers_duplicate(struct task_struct *from, struct task_struct *to)
                        continue;
 
                for (last = NULL; helper != NULL; helper = helper->dtha_next) {
-                       new = vzalloc(sizeof(dtrace_helper_action_t));
+                       new = kzalloc(sizeof(dtrace_helper_action_t),
+                                     GFP_KERNEL);
                        new->dtha_generation = helper->dtha_generation;
 
                        if ((dp = helper->dtha_predicate) != NULL) {
index f146d9ba851fef627144ce2f528fa3ea1c038b94..819fe3c114915de58fd85d1c21d657162781ff7a 100644 (file)
@@ -43,7 +43,7 @@ static dtrace_action_t *dtrace_ecb_aggregation_create(dtrace_ecb_t *ecb,
        dtrace_state_t          *state = ecb->dte_state;
        int                     err;
 
-       agg = vzalloc(sizeof(dtrace_aggregation_t));
+       agg = kzalloc(sizeof(dtrace_aggregation_t), GFP_KERNEL);
        if (agg == NULL)
                return NULL;
 
@@ -122,7 +122,7 @@ static dtrace_action_t *dtrace_ecb_aggregation_create(dtrace_ecb_t *ecb,
 
        ASSERT(ntuple != 0);
 err:
-       vfree(agg);
+       kfree(agg);
        return NULL;
 
 success:
@@ -176,7 +176,7 @@ void dtrace_ecb_aggregation_destroy(dtrace_ecb_t *ecb, dtrace_action_t *act)
        idr_remove(&state->dts_agg_idr, agg->dtag_id);
        state->dts_naggs--;
 
-       vfree(agg);
+       kfree(agg);
 }
 
 static int dtrace_ecb_action_add(dtrace_ecb_t *ecb, dtrace_actdesc_t *desc)
@@ -367,7 +367,7 @@ static int dtrace_ecb_action_add(dtrace_ecb_t *ecb, dtrace_actdesc_t *desc)
                        }
                }
 
-               action = vzalloc(sizeof(dtrace_action_t));
+               action = kzalloc(sizeof(dtrace_action_t), GFP_KERNEL);
                if (action == NULL)
                        return -ENOMEM;
 
@@ -439,7 +439,7 @@ static void dtrace_ecb_action_remove(dtrace_ecb_t *ecb)
                        if (DTRACEACT_ISAGG(act->dta_kind))
                                dtrace_ecb_aggregation_destroy(ecb, act);
                        else
-                               vfree(act);
+                               kfree(act);
                }
        }
 
@@ -533,7 +533,7 @@ static dtrace_ecb_t *dtrace_ecb_add(dtrace_state_t *state,
 
        ASSERT(MUTEX_HELD(&dtrace_lock));
 
-       ecb = vzalloc(sizeof(dtrace_ecb_t));
+       ecb = kzalloc(sizeof(dtrace_ecb_t), GFP_KERNEL);
        if (ecb == NULL)
                return NULL;
 
@@ -689,7 +689,7 @@ void dtrace_ecb_destroy(dtrace_ecb_t *ecb)
        ASSERT(state->dts_ecbs[epid - 1] == ecb);
        state->dts_ecbs[epid - 1] = NULL;
 
-       vfree(ecb);
+       kfree(ecb);
 }
 
 void dtrace_ecb_resize(dtrace_ecb_t *ecb)
index fecfe9531620f47259d9e2d52c4f847eedb267bb..117c3793b33f1c2030924ae7ec0649e38bb5664b 100644 (file)
@@ -39,7 +39,7 @@ dtrace_enabling_t *dtrace_enabling_create(dtrace_vstate_t *vstate)
 {
        dtrace_enabling_t       *enab;
 
-       enab = vzalloc(sizeof (dtrace_enabling_t));
+       enab = kzalloc(sizeof (dtrace_enabling_t), GFP_KERNEL);
        if (enab == NULL)
                return NULL;
 
@@ -95,7 +95,7 @@ static void dtrace_enabling_addlike(dtrace_enabling_t *enab,
         * We're going to create a new ECB description that matches the
         * specified ECB in every way, but has the specified probe description.
         */
-       new = vzalloc(sizeof (dtrace_ecbdesc_t));
+       new = kzalloc(sizeof (dtrace_ecbdesc_t), GFP_KERNEL);
 
        if ((pred = ecb->dted_pred.dtpdd_predicate) != NULL)
                dtrace_predicate_hold(pred);
@@ -147,7 +147,7 @@ void dtrace_enabling_destroy(dtrace_enabling_t *enab)
                        dtrace_actdesc_release(act, vstate);
                }
 
-               vfree(ep);
+               kfree(ep);
        }
 
        vfree(enab->dten_desc);
@@ -182,7 +182,7 @@ void dtrace_enabling_destroy(dtrace_enabling_t *enab)
                enab->dten_next->dten_prev = enab->dten_prev;
        }
 
-       vfree(enab);
+       kfree(enab);
 }
 
 int dtrace_enabling_retain(dtrace_enabling_t *enab)
index 1bdf49606e2b04ff7c42aa2cfdb9bc3577c1dc09..8c07769c4dcb9c649ba2cbb86b2f943e5c3a6fa2 100644 (file)
@@ -54,7 +54,7 @@ static uint_t dtrace_hash_str(char *p)
 dtrace_hash_t *dtrace_hash_create(uintptr_t stroffs, uintptr_t nextoffs,
                                  uintptr_t prevoffs)
 {
-       dtrace_hash_t   *hash = vzalloc(sizeof(dtrace_hash_t));
+       dtrace_hash_t   *hash = kzalloc(sizeof(dtrace_hash_t), GFP_KERNEL);
 
        if (hash == NULL)
                return NULL;
@@ -70,7 +70,7 @@ dtrace_hash_t *dtrace_hash_create(uintptr_t stroffs, uintptr_t nextoffs,
                                sizeof(dtrace_hashbucket_t *));
 
        if (hash->dth_tab == NULL) {
-               vfree(hash);
+               kfree(hash);
                return NULL;
        }
 
@@ -87,7 +87,7 @@ void dtrace_hash_destroy(dtrace_hash_t *hash)
 #endif
 
        vfree(hash->dth_tab);
-       vfree(hash);
+       kfree(hash);
 }
 
 static int dtrace_hash_resize(dtrace_hash_t *hash)
@@ -147,7 +147,7 @@ int dtrace_hash_add(dtrace_hash_t *hash, dtrace_probe_t *new)
                return 0;
        }
 
-       bucket = vzalloc(sizeof(dtrace_hashbucket_t));
+       bucket = kzalloc(sizeof(dtrace_hashbucket_t), GFP_KERNEL);
        if (bucket == NULL)
                return -ENOMEM;
 
@@ -191,6 +191,14 @@ dtrace_probe_t *dtrace_hash_lookup(dtrace_hash_t *hash,
        return NULL;
 }
 
+/*
+ * FIXME:
+ * It would be more accurate to calculate a lookup cost based on the number
+ * of buckets in the hash table slot, the length of the chain, and the length
+ * of the string being looked up.
+ * The hash tables can also be optimized by storing the hashval in each element
+ * rather than always performing string comparisons.
+ */
 int dtrace_hash_collisions(dtrace_hash_t *hash, dtrace_probe_t *template)
 {
        int                     hashval = DTRACE_HASHSTR(hash, template);
@@ -243,7 +251,7 @@ void dtrace_hash_remove(dtrace_hash_t *hash, dtrace_probe_t *probe)
                        ASSERT(hash->dth_nbuckets > 0);
 
                        hash->dth_nbuckets--;
-                       vfree(bucket);
+                       kfree(bucket);
 
                        return;
                }
index 01d21ab324097dbe70442219574cadd7f343ea40..c7fa70af41543221f1489012c9ca02a3f3ce0bd9 100644 (file)
@@ -38,7 +38,7 @@ dtrace_predicate_t *dtrace_predicate_create(dtrace_difo_t *dp)
        ASSERT(MUTEX_HELD(&dtrace_lock));
        ASSERT(dp->dtdo_refcnt != 0);
 
-       pred = vzalloc(sizeof (dtrace_predicate_t));
+       pred = kzalloc(sizeof (dtrace_predicate_t), GFP_KERNEL);
        if (pred == NULL)
                return NULL;
 
@@ -84,6 +84,6 @@ void dtrace_predicate_release(dtrace_predicate_t *pred,
 
        if (--pred->dtp_refcnt == 0) {
                dtrace_difo_release(dp, vstate);
-               vfree(pred);
+               kfree(pred);
        }
 }
index 30323781c399f20284ac44889ccb4c70c797f0cb..a57d5109c72bd3838f80e492fa6743393746a893 100644 (file)
@@ -42,6 +42,7 @@ ktime_t                               dtrace_chill_max =
                                                   500 * (NANOSEC / MILLISEC));
 
 dtrace_genid_t                 dtrace_probegen;
+struct kmem_cache              *dtrace_probe_cachep;
 
 static struct idr              dtrace_probe_idr;
 static uint64_t                        dtrace_vtime_references;
@@ -60,7 +61,7 @@ dtrace_id_t dtrace_probe_create(dtrace_provider_id_t prov, const char *mod,
        dtrace_id_t             id;
        int                     err;
 
-       probe = kzalloc(sizeof(dtrace_probe_t), __GFP_NOFAIL);
+       probe = kmem_cache_alloc(dtrace_probe_cachep, __GFP_NOFAIL);
 
        /*
         * The idr_pre_get() function should be called without holding locks.
@@ -83,13 +84,19 @@ again:
        }
 
        probe->dtpr_id = id;
-       probe->dtpr_gen = dtrace_probegen++;
-       probe->dtpr_mod = dtrace_strdup(mod);
-       probe->dtpr_func = dtrace_strdup(func);
-       probe->dtpr_name = dtrace_strdup(name);
+       probe->dtpr_ecb = NULL;
+       probe->dtpr_ecb_last = NULL;
        probe->dtpr_arg = arg;
+       probe->dtpr_predcache = DTRACE_CACHEIDNONE;
        probe->dtpr_aframes = aframes;
        probe->dtpr_provider = provider;
+       probe->dtpr_mod = dtrace_strdup(mod);
+       probe->dtpr_func = dtrace_strdup(func);
+       probe->dtpr_name = dtrace_strdup(name);
+       probe->dtpr_nextmod = probe->dtpr_prevmod = NULL;
+       probe->dtpr_nextfunc = probe->dtpr_prevfunc = NULL;
+       probe->dtpr_nextname = probe->dtpr_prevname = NULL;
+       probe->dtpr_gen = dtrace_probegen++;
 
        dtrace_hash_add(dtrace_bymod, probe);
        dtrace_hash_add(dtrace_byfunc, probe);
@@ -1256,11 +1263,15 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
 }
 EXPORT_SYMBOL(dtrace_probe);
 
-void dtrace_probe_init(void)
+int dtrace_probe_init(void)
 {
        dtrace_id_t     id;
        int             err;
 
+       dtrace_probe_cachep = KMEM_CACHE(dtrace_probe, SLAB_HWCACHE_ALIGN);
+       if (dtrace_probe_cachep == NULL)
+               return -ENOMEM;
+
        idr_init(&dtrace_probe_idr);
 
        /*
@@ -1286,13 +1297,14 @@ again:
        if (err == -EAGAIN)
                goto again;
 
-       ASSERT(id == 0);
+       return id == 0 ? 0 : -EAGAIN;
 }
 
 void dtrace_probe_exit(void)
 {
        idr_remove_all(&dtrace_probe_idr);
        idr_destroy(&dtrace_probe_idr);
+       kmem_cache_destroy(dtrace_probe_cachep);
 }
 
 void dtrace_probe_remove_id(dtrace_id_t id)
@@ -1340,9 +1352,9 @@ dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t prid, const char *mod,
 }
 EXPORT_SYMBOL(dtrace_probe_lookup);
 
-dtrace_probe_t *dtrace_probe_get_next(dtrace_id_t id)
+dtrace_probe_t *dtrace_probe_get_next(dtrace_id_t *idp)
 {
-       return idr_get_next(&dtrace_probe_idr, &id);
+       return idr_get_next(&dtrace_probe_idr, idp);
 }
 
 int dtrace_probe_for_each(int (*fn)(int id, void *p, void *data), void *data)
index 110300ee8a7bc535a4c6724282132361e896efb6..15964f858da54de8edd3feb2967e13427f05e2b8 100644 (file)
@@ -191,12 +191,12 @@ int dtrace_register(const char *name, const dtrace_pattr_t *pap, uint32_t priv,
                return -EINVAL;
        }
 
-       provider = vzalloc(sizeof (dtrace_provider_t));
+       provider = kzalloc(sizeof (dtrace_provider_t), GFP_KERNEL);
        if (provider == NULL)
                return -ENOMEM;
        provider->dtpv_name = dtrace_strdup(name);
        if (provider->dtpv_name == NULL) {
-               vfree(provider);
+               kfree(provider);
                return -ENOMEM;
        }
        provider->dtpv_attr = *pap;
@@ -464,7 +464,7 @@ int dtrace_unregister(dtrace_provider_id_t id)
                kfree(probe->dtpr_mod);
                kfree(probe->dtpr_func);
                kfree(probe->dtpr_name);
-               kfree(probe);
+               kmem_cache_free(dtrace_probe_cachep, probe);
 
                dtrace_probe_remove_id(probe_id);
        }
@@ -497,7 +497,7 @@ int dtrace_unregister(dtrace_provider_id_t id)
        }
 
        kfree(old->dtpv_name);
-       vfree(old);
+       kfree(old);
 
        return 0;
 }
@@ -625,13 +625,13 @@ int dtrace_meta_register(const char *name, const dtrace_mops_t *mops,
                return -EINVAL;
        }
 
-       meta = vzalloc(sizeof(dtrace_meta_t));
+       meta = kzalloc(sizeof(dtrace_meta_t), GFP_KERNEL);
        if (meta == NULL)
                return -ENOMEM;
        meta->dtm_mops = *mops;
-       meta->dtm_name = vmalloc(strlen(name) + 1);
+       meta->dtm_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
        if (meta->dtm_name == NULL) {
-               vfree(meta);
+               kfree(meta);
                return -ENOMEM;
        }
        strcpy(meta->dtm_name, name);
@@ -707,8 +707,8 @@ int dtrace_meta_unregister(dtrace_meta_provider_id_t id)
        mutex_unlock(&dtrace_lock);
        mutex_unlock(&dtrace_meta_lock);
 
-       vfree(old->dtm_name);
-       vfree(old);
+       kfree(old->dtm_name);
+       kfree(old);
 
        return 0;
 }
index 950dfe00b3ac5917dd92cee5bc9f440204817ea5..5d9cc9d2f560e05026789a4d5631ff565b935a74 100644 (file)
@@ -67,6 +67,8 @@ DEFINE_MUTEX(fasttrap_count_mtx);
 static uint_t                  fasttrap_cleanup_state;
 static uint_t                  fasttrap_cleanup_work;
 
+static struct kmem_cache       *tracepoint_cachep;
+
 /*
  * Generation count on modifications to the global tracepoint lookup table.
  */
@@ -354,7 +356,8 @@ again:
                 */
                rc = dtrace_tracepoint_enable(pid, pc, &new_tp->ftt_mtp);
                if (rc != 0) {
-                       pr_warn("FASTTRAP: Failed to enable tp: rc %d\n", rc);
+                       pr_warn("FASTTRAP: Failed to enable tp "
+                               "(PID %d, pc %lx): rc %d\n", pid, pc, rc);
                        rc = FASTTRAP_ENABLE_PARTIAL;
                }
 
@@ -755,7 +758,22 @@ static uint64_t fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg,
 
 static void fasttrap_pid_destroy(void *arg, dtrace_id_t id, void *parg)
 {
-       /* FIXME */
+       fasttrap_probe_t        *probe = parg;
+       int                     i;
+
+       ASSERT(probe != NULL);
+       ASSERT(!probe->ftp_enabled);
+       ASSERT(atomic_read(&fasttrap_total) >= probe->ftp_ntps);
+
+       atomic_add(-probe->ftp_ntps, &fasttrap_total);
+
+       if (probe->ftp_gen + 1 >= fasttrap_mod_gen)
+               fasttrap_mod_barrier(probe->ftp_gen);
+
+       for (i = 0; i < probe->ftp_ntps; i++)
+               kmem_cache_free(tracepoint_cachep, probe->ftp_tps[i].fit_tp);
+
+       kfree(probe);
 }
 
 static const dtrace_pattr_t pid_attr = {
@@ -871,7 +889,7 @@ void fasttrap_meta_create_probe(void *arg, void *parg,
        ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs;
        ASSERT(ntps > 0);
 
-       pp = vzalloc(offsetof(fasttrap_probe_t, ftp_tps[ntps]));
+       pp = kzalloc(offsetof(fasttrap_probe_t, ftp_tps[ntps]), GFP_KERNEL);
        if (pp == NULL) {
                pr_warn("Unable to create probe %s: out-of-memory\n",
                        dhpb->dthpb_name);
@@ -881,7 +899,7 @@ void fasttrap_meta_create_probe(void *arg, void *parg,
 
        atomic_add(ntps, &fasttrap_total);
        if (atomic_read(&fasttrap_total) > fasttrap_max) {
-               vfree(pp);
+               kfree(pp);
                atomic_add(-ntps, &fasttrap_total);
                mutex_unlock(&provider->ftp_cmtx);
                return;
@@ -898,13 +916,17 @@ void fasttrap_meta_create_probe(void *arg, void *parg,
         * First create a tracepoint for each actual point of interest.
         */
        for (i = 0; i < dhpb->dthpb_noffs; i++) {
-               tp = vzalloc(sizeof(fasttrap_tracepoint_t));
+               tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
                if (tp == NULL)
                        goto fail;
 
                tp->ftt_proc = provider->ftp_proc;
                tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_offs[i];
                tp->ftt_pid = provider->ftp_pid;
+               memset(&tp->ftt_mtp, 0, sizeof(fasttrap_machtp_t));
+               tp->ftt_ids = NULL;
+               tp->ftt_retids = NULL;
+               tp->ftt_next = NULL;
 
                dt_dbg_dof("        Tracepoint at 0x%lx (0x%llx + 0x%x)\n",
                           tp->ftt_pc, dhpb->dthpb_base, dhpb->dthpb_offs[i]);
@@ -922,7 +944,7 @@ void fasttrap_meta_create_probe(void *arg, void *parg,
         * Then create a tracepoint for each is-enabled point.
         */
        for (j = 0; i < ntps; i++, j++) {
-               tp = vzalloc(sizeof(fasttrap_tracepoint_t));
+               tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
                if (tp == NULL)
                        goto fail;
 
@@ -930,6 +952,10 @@ void fasttrap_meta_create_probe(void *arg, void *parg,
                tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_enoffs[j];
                tp->ftt_pid = provider->ftp_pid;
 
+               tp->ftt_ids = NULL;
+               tp->ftt_retids = NULL;
+               tp->ftt_next = NULL;
+
                pp->ftp_tps[i].fit_tp = tp;
                pp->ftp_tps[i].fit_id.fti_probe = pp;
                pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_IS_ENABLED;
@@ -962,9 +988,9 @@ fail:
                dhpb->dthpb_name);
 
        for (i = 0; i < ntps; i++)
-               vfree(pp->ftp_tps[i].fit_tp);
+               kmem_cache_free(tracepoint_cachep, pp->ftp_tps[i].fit_tp);
 
-       vfree(pp);
+       kfree(pp);
        atomic_add(-ntps, &fasttrap_total);
        mutex_unlock(&provider->ftp_cmtx);
 }
@@ -1013,7 +1039,7 @@ static void fasttrap_proc_release(fasttrap_proc_t *proc)
 
        mutex_unlock(&bucket->ftb_mtx);
 
-       vfree(fprc);
+       kfree(fprc);
 }
 
 static void fasttrap_provider_free(fasttrap_provider_t *provider)
@@ -1040,7 +1066,7 @@ static void fasttrap_provider_free(fasttrap_provider_t *provider)
 
        fasttrap_proc_release(provider->ftp_proc);
 
-       vfree(provider);
+       kfree(provider);
 
        unregister_pid_provider(pid);
 }
@@ -1074,7 +1100,7 @@ static fasttrap_proc_t *fasttrap_proc_lookup(pid_t pid)
         */
        mutex_unlock(&bucket->ftb_mtx);
 
-       new_fprc = vzalloc(sizeof(fasttrap_proc_t));
+       new_fprc = kzalloc(sizeof(fasttrap_proc_t), GFP_KERNEL);
        if (new_fprc == NULL)
                return NULL;
 
@@ -1100,7 +1126,7 @@ static fasttrap_proc_t *fasttrap_proc_lookup(pid_t pid)
                               fprc->ftpc_rcount);
                        mutex_unlock(&fprc->ftpc_mtx);
 
-                       vfree(new_fprc);
+                       kfree(new_fprc);
 
                        return fprc;
                }
@@ -1167,7 +1193,7 @@ static fasttrap_provider_t *fasttrap_provider_lookup(pid_t pid,
        if ((proc = fasttrap_proc_lookup(pid)) == NULL)
                goto fail;
 
-       if ((new_fp = vzalloc(sizeof(fasttrap_provider_t))) == NULL)
+       if ((new_fp = kzalloc(sizeof(fasttrap_provider_t), GFP_KERNEL)) == NULL)
                goto fail;
 
        new_fp->ftp_pid = pid;
@@ -1376,8 +1402,7 @@ static void fasttrap_pid_cleanup_cb(struct work_struct *work)
                                        *fpp = fp->ftp_next;
                                        fasttrap_provider_free(fp);
 
-                                       module_put(THIS_MODULE);
-                               }
+                                       module_put(THIS_MODULE); }
                        }
 
                        mutex_unlock(&bucket->ftb_mtx);
@@ -1579,6 +1604,8 @@ int fasttrap_dev_init(void)
        dtrace_fasttrap_exec_ptr = &fasttrap_exec_exit;
 #endif
 
+        tracepoint_cachep = KMEM_CACHE(fasttrap_tracepoint, 0);
+
        fasttrap_max = FASTTRAP_MAX_DEFAULT;
        atomic_set(&fasttrap_total, 0);
 
@@ -1722,6 +1749,8 @@ void fasttrap_dev_exit(void)
                vfree(fasttrap_procs.fth_table);
        fasttrap_procs.fth_nent = 0;
 
+       kmem_cache_destroy(tracepoint_cachep);
+
 #ifdef FIXME
        ASSERT(dtrace_fasttrap_exec_ptr == &fasttrap_exec_exit);
        dtrace_fasttrap_exec_ptr = NULL;
index 2f5034fdbb0108e13cc3d29ef5cd18ea80d5d531..48ddf39b12dc78bac88190b29254c7b8d36797e6 100644 (file)
@@ -418,6 +418,7 @@ extern struct mutex         dtrace_provider_lock;
 extern struct mutex            dtrace_meta_lock;
 
 extern dtrace_genid_t          dtrace_probegen;
+extern struct kmem_cache       *dtrace_probe_cachep;
 
 extern dtrace_pops_t           dtrace_provider_ops;
 
@@ -518,11 +519,11 @@ extern int dtrace_probe_enable(const dtrace_probedesc_t *,
 extern void dtrace_probe_description(const dtrace_probe_t *,
                                     dtrace_probedesc_t *);
 extern void dtrace_probe_provide(dtrace_probedesc_t *, dtrace_provider_t *);
-extern void dtrace_probe_init(void);
+extern int dtrace_probe_init(void);
 extern void dtrace_probe_exit(void);
 extern void dtrace_probe_remove_id(dtrace_id_t);
 extern dtrace_probe_t *dtrace_probe_lookup_id(dtrace_id_t);
-extern dtrace_probe_t *dtrace_probe_get_next(dtrace_id_t);
+extern dtrace_probe_t *dtrace_probe_get_next(dtrace_id_t *);
 extern int dtrace_probe_for_each(int (*)(int, void *, void *), void *);
 
 /*
index 4f58a78c0893ad18d0a6789af4fb6e35e11f75c3..655bb748d76735454e15379643b0db999e9002e8 100644 (file)
@@ -172,7 +172,7 @@ static void profile_create(ktime_t interval, const char *name, int kind)
        if (dtrace_probe_lookup(profile_id, NULL, NULL, name) != 0)
                return;
 
-       prof = vzalloc(sizeof(profile_probe_t));
+       prof = kzalloc(sizeof(profile_probe_t), GFP_KERNEL);
        if (prof == NULL) {
                pr_warn("Unable to create probe %s: out-of-memory\n", name);
                return;
@@ -180,7 +180,7 @@ static void profile_create(ktime_t interval, const char *name, int kind)
 
        atomic_inc(&profile_total);
        if (atomic_read(&profile_total) > profile_max) {
-               vfree(prof);
+               kfree(prof);
                atomic_dec(&profile_total);
                return;
        }
@@ -396,7 +396,7 @@ void profile_destroy(void *arg, dtrace_id_t id, void *parg)
        profile_probe_t *prof = parg;
 
        ASSERT(prof->prof_cyclic == CYCLIC_NONE);
-       vfree(prof);
+       kfree(prof);
 
        ASSERT(atomic_read(&profile_total) >= 1);
        atomic_dec(&profile_total);
index 4868db390505a919b4b85da58eb24701531259c3..661c03fba1224500c7fad8fc6a3353326f61e3cb 100644 (file)
@@ -162,9 +162,9 @@ void sdt_provide_module(void *arg, struct module *mp)
                        }
                }
 
-               nname = vmalloc(len = strlen(name) + 1);
+               nname = kmalloc(len = strlen(name) + 1, GFP_KERNEL);
                if (nname == NULL) {
-                       pr_warn("Unable to create probe%s: out-of-memory\n",
+                       pr_warn("Unable to create probe %s: out-of-memory\n",
                                name);
                        continue;
                }
@@ -179,7 +179,7 @@ void sdt_provide_module(void *arg, struct module *mp)
 
                nname[i] = '\0';
 
-               sdp = vzalloc(sizeof(sdt_probe_t));
+               sdp = kzalloc(sizeof(sdt_probe_t), GFP_KERNEL);
                if (sdp == NULL) {
                        pr_warn("Unable to create probe %s: out-of-memory\n",
                                nname);
@@ -331,9 +331,9 @@ void sdt_destroy(void *arg, dtrace_id_t id, void *parg)
                else
                        sdt_probetab[ndx] = sdp->sdp_hashnext;
 
-               vfree(sdp->sdp_name);
+               kfree(sdp->sdp_name);
                sdp = sdp->sdp_next;
-               vfree(old);
+               kfree(old);
        }
 }
 
index addeb8ef43b2cad1629746d989c155141e3903fc..a4c6c3c2deecd0b2390b003833b6b6f30251c7f0 100644 (file)
@@ -72,7 +72,8 @@ void systrace_provide(void *arg, const dtrace_probedesc_t *desc)
                else if (sz > 5 && memcmp(nm, "stub_", 5) == 0)
                        nm += 5;
 
-               if (dtrace_probe_lookup(syscall_id, NULL, nm, "entry") != 0)
+               if (dtrace_probe_lookup(syscall_id, dtrace_kmod->name, nm,
+                                       "entry") != 0)
                        continue;
 
                dtrace_probe_create(syscall_id, dtrace_kmod->name, nm, "entry",