From 8d3c24563ff1052df486bdcfd9c325464a435476 Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Fri, 20 Sep 2013 09:53:05 -0400 Subject: [PATCH] dtrace: Various memory allocation fixes (leaks, footprint reduction, ...) Orabug: 17488207 Signed-off-by: Kris Van Hees --- dtrace/dtrace_actdesc.c | 4 +- dtrace/dtrace_dev.c | 23 ++++++++--- dtrace/dtrace_dif.c | 8 ++-- dtrace/dtrace_dof.c | 32 +++++++++------- dtrace/dtrace_ecb.c | 14 +++---- dtrace/dtrace_enable.c | 8 ++-- dtrace/dtrace_hash.c | 18 ++++++--- dtrace/dtrace_predicate.c | 4 +- dtrace/dtrace_probe.c | 30 ++++++++++----- dtrace/dtrace_ptofapi.c | 18 ++++----- dtrace/fasttrap_dev.c | 59 +++++++++++++++++++++-------- dtrace/include/dtrace/dtrace_impl.h | 5 ++- dtrace/profile_dev.c | 6 +-- dtrace/sdt_dev.c | 10 ++--- dtrace/systrace_dev.c | 3 +- 15 files changed, 155 insertions(+), 87 deletions(-) diff --git a/dtrace/dtrace_actdesc.c b/dtrace/dtrace_actdesc.c index 86f66a2131de8..be58b37a55a49 100644 --- a/dtrace/dtrace_actdesc.c +++ b/dtrace/dtrace_actdesc.c @@ -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); } diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c index 853a3ef720121..e4d5da6f4f928 100644 --- a/dtrace/dtrace_dev.c +++ b/dtrace/dtrace_dev.c @@ -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); diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c index e2fa3365d481b..d6339a8dc558d 100644 --- a/dtrace/dtrace_dif.c +++ b/dtrace/dtrace_dif.c @@ -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) diff --git a/dtrace/dtrace_dof.c b/dtrace/dtrace_dof.c index 179c65f28d52a..08a2e43639a02 100644 --- a/dtrace/dtrace_dof.c +++ b/dtrace/dtrace_dof.c @@ -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 : "", + 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) { diff --git a/dtrace/dtrace_ecb.c b/dtrace/dtrace_ecb.c index f146d9ba851fe..819fe3c114915 100644 --- a/dtrace/dtrace_ecb.c +++ b/dtrace/dtrace_ecb.c @@ -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) diff --git a/dtrace/dtrace_enable.c b/dtrace/dtrace_enable.c index fecfe9531620f..117c3793b33f1 100644 --- a/dtrace/dtrace_enable.c +++ b/dtrace/dtrace_enable.c @@ -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) diff --git a/dtrace/dtrace_hash.c b/dtrace/dtrace_hash.c index 1bdf49606e2b0..8c07769c4dcb9 100644 --- a/dtrace/dtrace_hash.c +++ b/dtrace/dtrace_hash.c @@ -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; } diff --git a/dtrace/dtrace_predicate.c b/dtrace/dtrace_predicate.c index 01d21ab324097..c7fa70af41543 100644 --- a/dtrace/dtrace_predicate.c +++ b/dtrace/dtrace_predicate.c @@ -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); } } diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c index 30323781c399f..a57d5109c72bd 100644 --- a/dtrace/dtrace_probe.c +++ b/dtrace/dtrace_probe.c @@ -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) diff --git a/dtrace/dtrace_ptofapi.c b/dtrace/dtrace_ptofapi.c index 110300ee8a7bc..15964f858da54 100644 --- a/dtrace/dtrace_ptofapi.c +++ b/dtrace/dtrace_ptofapi.c @@ -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; } diff --git a/dtrace/fasttrap_dev.c b/dtrace/fasttrap_dev.c index 950dfe00b3ac5..5d9cc9d2f560e 100644 --- a/dtrace/fasttrap_dev.c +++ b/dtrace/fasttrap_dev.c @@ -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; diff --git a/dtrace/include/dtrace/dtrace_impl.h b/dtrace/include/dtrace/dtrace_impl.h index 2f5034fdbb010..48ddf39b12dc7 100644 --- a/dtrace/include/dtrace/dtrace_impl.h +++ b/dtrace/include/dtrace/dtrace_impl.h @@ -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 *); /* diff --git a/dtrace/profile_dev.c b/dtrace/profile_dev.c index 4f58a78c0893a..655bb748d7673 100644 --- a/dtrace/profile_dev.c +++ b/dtrace/profile_dev.c @@ -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); diff --git a/dtrace/sdt_dev.c b/dtrace/sdt_dev.c index 4868db390505a..661c03fba1224 100644 --- a/dtrace/sdt_dev.c +++ b/dtrace/sdt_dev.c @@ -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); } } diff --git a/dtrace/systrace_dev.c b/dtrace/systrace_dev.c index addeb8ef43b2c..a4c6c3c2deecd 100644 --- a/dtrace/systrace_dev.c +++ b/dtrace/systrace_dev.c @@ -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", -- 2.50.1