From owner-svn-src-all@FreeBSD.ORG Fri Aug 16 16:59:56 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 3AD6F5A0; Fri, 16 Aug 2013 16:59:56 +0000 (UTC) (envelope-from markjdb@gmail.com) Received: from mail-qc0-x22c.google.com (mail-qc0-x22c.google.com [IPv6:2607:f8b0:400d:c01::22c]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B8AE22422; Fri, 16 Aug 2013 16:59:55 +0000 (UTC) Received: by mail-qc0-f172.google.com with SMTP id a1so1231351qcx.17 for ; Fri, 16 Aug 2013 09:59:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=N/zLedn8we8rVm1FHO7ypv0MkuOvRLci/C9YV5JeXWg=; b=AIAi8azZtlU1vnORAsVa8aXYyQUImStWFr1Lwt6Q/QYfCTgeAvdVeHBTdSU03Nj2Df 8Vp/yTyGCq/J9kGu2or2sibNOI/luoO6G4mBF7+Weu+Ve8yAHQCP4UNh/zdcinrynHh1 OyS4KssAkfuYk4wEQXGcwPMEdeRP8NerJ7XDJ1nj5QZ666USO0es3tks+fKA1xtBT5X+ OQGwyLo64rsMkjRsGU0IQLlc3Hk0mRbuhEF9/Oi92R7o8T8leBbn+tf4IxvnD/cxMc31 TPQldFhDy8Vo9O5CiBqfw2pxq6rb6RiZmqWDw7VtdlFO3JbNOL8Q9wAM6MMBYsLlx0+7 kacg== X-Received: by 10.224.45.69 with SMTP id d5mr2333709qaf.108.1376672394843; Fri, 16 Aug 2013 09:59:54 -0700 (PDT) Received: from charmander.sandvine.com ([64.7.137.182]) by mx.google.com with ESMTPSA id 5sm2458052qel.1.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 16 Aug 2013 09:59:54 -0700 (PDT) Sender: Mark Johnston Date: Fri, 16 Aug 2013 13:00:27 -0400 From: Mark Johnston To: John Baldwin Subject: Re: svn commit: r254309 - in head: share/man/man9 sys/cddl/contrib/opensolaris/uts/common/dtrace sys/cddl/dev/dtrace sys/cddl/dev/sdt sys/kern sys/sys Message-ID: <20130816170027.GA1888@charmander.sandvine.com> References: <201308140042.r7E0gMtf054550@svn.freebsd.org> <201308140819.13854.jhb@freebsd.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <201308140819.13854.jhb@freebsd.org> User-Agent: Mutt/1.5.21 (2010-09-15) Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 16 Aug 2013 16:59:56 -0000 On Wed, Aug 14, 2013 at 08:19:13AM -0400, John Baldwin wrote: > On Tuesday, August 13, 2013 8:42:22 pm Mark Johnston wrote: > > Author: markj > > Date: Wed Aug 14 00:42:21 2013 > > New Revision: 254309 > > URL: http://svnweb.freebsd.org/changeset/base/254309 > > > > Log: > > Use kld_{load,unload} instead of mod_{load,unload} for the linker file load > > and unload event handlers added in r254266. > > > > Reported by: jhb > > X-MFC with: r254266 > > Thanks! BTW, it would be really nice to replace HWPMC_HOOKS in kern_linker.c with > EVENTHANDLER calls. I think kld_load would just work (though you might need to > downgrade the lock before you run it). For kld_unload it seems you want two events, > a kld_unload_try for your newly added event (since it can reject a kld_unload), and > perhaps kld_unload at the end where the current HWPMC_HOOK is. Just an idea if > someone is looking for something to do. I know there are other modules that need > to hook into linker events like this, and making HWPMC_HOOKS more generic would be > a big help. Ok, I have a couple of patches which do this. The first diff fixes the locking issue in linker_file_lookup_set(). It ensures that this function is always called with the linker lock held; it's only called from kern_linker.c and sdt.c. The assertion in linker_file_lookup_set() checks for !cold to avoid adding some unnecessary locking in linker_preload(). The second diff below renames the kld_unload event to kld_unload_try, adds a kld_unload eventhandler, and converts hwpmc(4) to use kld_load and kld_unload. So now the kld_load and kld_unload handlers are invoked with the shared lock held, and the kld_unload_try handlers are invoked with the exclusive lock held. I've done a bunch of testing with module loads/unloads and made sure that the hwpmc and DTrace handlers are being called correctly. Would you be able to review the diff when you have a chance? The combined diff is also here: http://people.freebsd.org/~markj/patches/hwpmc-eh/hwpmc-eh-2.diff Thanks! -Mark diff 1: diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 3e500f3..528666c 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -81,6 +81,10 @@ TUNABLE_INT("debug.kld_debug", &kld_debug); if (!cold) \ sx_assert(&kld_sx, SX_XLOCKED); \ } while (0) +#define KLD_LOCK_READ_ASSERT() do { \ + if (!cold) \ + sx_assert(&kld_sx, SX_LOCKED); \ +} while (0) /* * static char *linker_search_path(const char *name, struct mod_depend @@ -208,6 +212,8 @@ linker_file_sysinit(linker_file_t lf) KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", lf->filename)); + KLD_LOCK_ASSERT(); + if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0) return; /* @@ -233,6 +239,7 @@ linker_file_sysinit(linker_file_t lf) * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. */ + KLD_UNLOCK(); mtx_lock(&Giant); for (sipp = start; sipp < stop; sipp++) { if ((*sipp)->subsystem == SI_SUB_DUMMY) @@ -242,6 +249,7 @@ linker_file_sysinit(linker_file_t lf) (*((*sipp)->func)) ((*sipp)->udata); } mtx_unlock(&Giant); + KLD_LOCK(); } static void @@ -252,6 +260,8 @@ linker_file_sysuninit(linker_file_t lf) KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n", lf->filename)); + KLD_LOCK_ASSERT(); + if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop, NULL) != 0) return; @@ -279,6 +289,7 @@ linker_file_sysuninit(linker_file_t lf) * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. */ + KLD_UNLOCK(); mtx_lock(&Giant); for (sipp = start; sipp < stop; sipp++) { if ((*sipp)->subsystem == SI_SUB_DUMMY) @@ -288,6 +299,7 @@ linker_file_sysuninit(linker_file_t lf) (*((*sipp)->func)) ((*sipp)->udata); } mtx_unlock(&Giant); + KLD_LOCK(); } static void @@ -299,13 +311,17 @@ linker_file_register_sysctls(linker_file_t lf) ("linker_file_register_sysctls: registering SYSCTLs for %s\n", lf->filename)); + KLD_LOCK_ASSERT(); + if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) return; + KLD_UNLOCK(); sysctl_lock(); for (oidp = start; oidp < stop; oidp++) sysctl_register_oid(*oidp); sysctl_unlock(); + KLD_LOCK(); } static void @@ -316,13 +332,17 @@ linker_file_unregister_sysctls(linker_file_t lf) KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs" " for %s\n", lf->filename)); + KLD_LOCK_ASSERT(); + if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) return; + KLD_UNLOCK(); sysctl_lock(); for (oidp = start; oidp < stop; oidp++) sysctl_unregister_oid(*oidp); sysctl_unlock(); + KLD_LOCK(); } static int @@ -335,6 +355,8 @@ linker_file_register_modules(linker_file_t lf) KLD_DPF(FILE, ("linker_file_register_modules: registering modules" " in %s\n", lf->filename)); + KLD_LOCK_ASSERT(); + if (linker_file_lookup_set(lf, "modmetadata_set", &start, &stop, NULL) != 0) { /* @@ -421,10 +443,8 @@ linker_load_file(const char *filename, linker_file_t *result) return (error); } modules = !TAILQ_EMPTY(&lf->modules); - KLD_UNLOCK(); linker_file_register_sysctls(lf); linker_file_sysinit(lf); - KLD_LOCK(); lf->flags |= LINKER_FILE_LINKED; /* @@ -674,10 +694,8 @@ linker_file_unload(linker_file_t file, int flags) */ if (file->flags & LINKER_FILE_LINKED) { file->flags &= ~LINKER_FILE_LINKED; - KLD_UNLOCK(); linker_file_sysuninit(file); linker_file_unregister_sysctls(file); - KLD_LOCK(); } TAILQ_REMOVE(&linker_files, file, link); @@ -746,15 +764,9 @@ int linker_file_lookup_set(linker_file_t file, const char *name, void *firstp, void *lastp, int *countp) { - int error, locked; - locked = KLD_LOCKED(); - if (!locked) - KLD_LOCK(); - error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp); - if (!locked) - KLD_UNLOCK(); - return (error); + KLD_LOCK_READ_ASSERT(); + return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp)); } /* @@ -1648,11 +1660,13 @@ restart: lf->filename); goto fail; } + KLD_LOCK(); linker_file_register_modules(lf); if (linker_file_lookup_set(lf, "sysinit_set", &si_start, &si_stop, NULL) == 0) sysinit_add(si_start, si_stop); linker_file_register_sysctls(lf); + KLD_UNLOCK(); lf->flags |= LINKER_FILE_LINKED; continue; fail: --- diff 2: diff --git a/share/man/man9/EVENTHANDLER.9 b/share/man/man9/EVENTHANDLER.9 index c3b646d..d6e7556 100644 --- a/share/man/man9/EVENTHANDLER.9 +++ b/share/man/man9/EVENTHANDLER.9 @@ -202,6 +202,8 @@ Callbacks invoked when a BPF listener attaches to/detaches from network interfac .It Vt kld_load Callbacks invoked after a linker file has been loaded. .It Vt kld_unload +Callbacks invoked after a linker file has been successfully unloaded. +.It Vt kld_unload_try Callbacks invoked before a linker file is about to be unloaded. These callbacks may be used to return an error and prevent the unload from proceeding. diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 9c007e7..babc42c4 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -242,7 +242,7 @@ int dtrace_in_probe; /* non-zero if executing a probe */ uintptr_t dtrace_in_probe_addr; /* Address of invop when already in probe */ #endif static eventhandler_tag dtrace_kld_load_tag; -static eventhandler_tag dtrace_kld_unload_tag; +static eventhandler_tag dtrace_kld_unload_try_tag; #endif /* @@ -15351,7 +15351,7 @@ dtrace_kld_load(void *arg __unused, linker_file_t lf) } static void -dtrace_kld_unload(void *arg __unused, linker_file_t lf, int *error) +dtrace_kld_unload_try(void *arg __unused, linker_file_t lf, int *error) { if (*error != 0) diff --git a/sys/cddl/dev/dtrace/dtrace_load.c b/sys/cddl/dev/dtrace/dtrace_load.c index f37d593..05436fe 100644 --- a/sys/cddl/dev/dtrace/dtrace_load.c +++ b/sys/cddl/dev/dtrace/dtrace_load.c @@ -59,8 +59,8 @@ dtrace_load(void *dummy) /* Register callbacks for linker file load and unload events. */ dtrace_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, dtrace_kld_load, NULL, EVENTHANDLER_PRI_ANY); - dtrace_kld_unload_tag = EVENTHANDLER_REGISTER(kld_unload, - dtrace_kld_unload, NULL, EVENTHANDLER_PRI_ANY); + dtrace_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try, + dtrace_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY); /* * Initialise the mutexes without 'witness' because the dtrace diff --git a/sys/cddl/dev/dtrace/dtrace_unload.c b/sys/cddl/dev/dtrace/dtrace_unload.c index 9e37114..e9bd53c 100644 --- a/sys/cddl/dev/dtrace/dtrace_unload.c +++ b/sys/cddl/dev/dtrace/dtrace_unload.c @@ -68,7 +68,7 @@ dtrace_unload() dtrace_provider = NULL; EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag); - EVENTHANDLER_DEREGISTER(kld_unload, dtrace_kld_unload_tag); + EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag); if ((state = dtrace_anon_grab()) != NULL) { /* diff --git a/sys/cddl/dev/sdt/sdt.c b/sys/cddl/dev/sdt/sdt.c index a1cd1e2..80f676f 100644 --- a/sys/cddl/dev/sdt/sdt.c +++ b/sys/cddl/dev/sdt/sdt.c @@ -59,7 +59,7 @@ static int sdt_unload(void *); static void sdt_create_provider(struct sdt_provider *); static void sdt_create_probe(struct sdt_probe *); static void sdt_kld_load(void *, struct linker_file *); -static void sdt_kld_unload(void *, struct linker_file *, int *); +static void sdt_kld_unload_try(void *, struct linker_file *, int *); static MALLOC_DEFINE(M_SDT, "SDT", "DTrace SDT providers"); @@ -95,7 +95,7 @@ static struct cdev *sdt_cdev; static TAILQ_HEAD(, sdt_provider) sdt_prov_list; eventhandler_tag sdt_kld_load_tag; -eventhandler_tag sdt_kld_unload_tag; +eventhandler_tag sdt_kld_unload_try_tag; static void sdt_create_provider(struct sdt_provider *prov) @@ -260,7 +260,7 @@ sdt_kld_load(void *arg __unused, struct linker_file *lf) } static void -sdt_kld_unload(void *arg __unused, struct linker_file *lf, int *error __unused) +sdt_kld_unload_try(void *arg __unused, struct linker_file *lf, int *error __unused) { struct sdt_provider *prov, **curr, **begin, **end, *tmp; @@ -315,8 +315,8 @@ sdt_load(void *arg __unused) sdt_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, sdt_kld_load, NULL, EVENTHANDLER_PRI_ANY); - sdt_kld_unload_tag = EVENTHANDLER_REGISTER(kld_unload, sdt_kld_unload, - NULL, EVENTHANDLER_PRI_ANY); + sdt_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try, + sdt_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY); /* Pick up probes from the kernel and already-loaded linker files. */ linker_file_foreach(sdt_linker_file_cb, NULL); @@ -328,7 +328,7 @@ sdt_unload(void *arg __unused) struct sdt_provider *prov, *tmp; EVENTHANDLER_DEREGISTER(kld_load, sdt_kld_load_tag); - EVENTHANDLER_DEREGISTER(kld_unload, sdt_kld_unload_tag); + EVENTHANDLER_DEREGISTER(kld_unload_try, sdt_kld_unload_try_tag); sdt_probe_func = sdt_probe_stub; diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 150c69a..858b319 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -132,7 +132,8 @@ static int *pmc_pmcdisp; /* PMC row dispositions */ /* various event handlers */ -static eventhandler_tag pmc_exit_tag, pmc_fork_tag; +static eventhandler_tag pmc_exit_tag, pmc_fork_tag, pmc_kld_load_tag, + pmc_kld_unload_tag; /* Module statistics */ struct pmc_op_getdriverstats pmc_stats; @@ -1476,50 +1477,6 @@ pmc_process_csw_out(struct thread *td) } /* - * Log a KLD operation. - */ - -static void -pmc_process_kld_load(struct pmckern_map_in *pkm) -{ - struct pmc_owner *po; - - sx_assert(&pmc_sx, SX_LOCKED); - - /* - * Notify owners of system sampling PMCs about KLD operations. - */ - - LIST_FOREACH(po, &pmc_ss_owners, po_ssnext) - if (po->po_flags & PMC_PO_OWNS_LOGFILE) - pmclog_process_map_in(po, (pid_t) -1, pkm->pm_address, - (char *) pkm->pm_file); - - /* - * TODO: Notify owners of (all) process-sampling PMCs too. - */ - - return; -} - -static void -pmc_process_kld_unload(struct pmckern_map_out *pkm) -{ - struct pmc_owner *po; - - sx_assert(&pmc_sx, SX_LOCKED); - - LIST_FOREACH(po, &pmc_ss_owners, po_ssnext) - if (po->po_flags & PMC_PO_OWNS_LOGFILE) - pmclog_process_map_out(po, (pid_t) -1, - pkm->pm_address, pkm->pm_address + pkm->pm_size); - - /* - * TODO: Notify owners of process-sampling PMCs. - */ -} - -/* * A mapping change for a process. */ @@ -1833,8 +1790,6 @@ const char *pmc_hooknames[] = { "CSW-IN", "CSW-OUT", "SAMPLE", - "KLDLOAD", - "KLDUNLOAD", "MMAP", "MUNMAP", "CALLCHAIN-NMI", @@ -2002,17 +1957,6 @@ pmc_hook_handler(struct thread *td, int function, void *arg) pmc_process_samples(PCPU_GET(cpuid), PMC_SR); break; - - case PMC_FN_KLD_LOAD: - sx_assert(&pmc_sx, SX_LOCKED); - pmc_process_kld_load((struct pmckern_map_in *) arg); - break; - - case PMC_FN_KLD_UNLOAD: - sx_assert(&pmc_sx, SX_LOCKED); - pmc_process_kld_unload((struct pmckern_map_out *) arg); - break; - case PMC_FN_MMAP: sx_assert(&pmc_sx, SX_LOCKED); pmc_process_mmap(td, (struct pmckern_map_in *) arg); @@ -4644,6 +4588,47 @@ pmc_process_fork(void *arg __unused, struct proc *p1, struct proc *newproc, sx_xunlock(&pmc_sx); } +static void +pmc_kld_load(void *arg __unused, linker_file_t lf) +{ + struct pmc_owner *po; + + sx_slock(&pmc_sx); + + /* + * Notify owners of system sampling PMCs about KLD operations. + */ + LIST_FOREACH(po, &pmc_ss_owners, po_ssnext) + if (po->po_flags & PMC_PO_OWNS_LOGFILE) + pmclog_process_map_in(po, (pid_t) -1, + (uintfptr_t) lf->address, lf->filename); + + /* + * TODO: Notify owners of (all) process-sampling PMCs too. + */ + + sx_sunlock(&pmc_sx); +} + +static void +pmc_kld_unload(void *arg __unused, const char *filename __unused, + caddr_t address, size_t size) +{ + struct pmc_owner *po; + + sx_slock(&pmc_sx); + + LIST_FOREACH(po, &pmc_ss_owners, po_ssnext) + if (po->po_flags & PMC_PO_OWNS_LOGFILE) + pmclog_process_map_out(po, (pid_t) -1, + (uintfptr_t) address, (uintfptr_t) address + size); + + /* + * TODO: Notify owners of process-sampling PMCs. + */ + + sx_sunlock(&pmc_sx); +} /* * initialization @@ -4913,6 +4898,12 @@ pmc_initialize(void) pmc_fork_tag = EVENTHANDLER_REGISTER(process_fork, pmc_process_fork, NULL, EVENTHANDLER_PRI_ANY); + /* register kld event handlers */ + pmc_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, pmc_kld_load, + NULL, EVENTHANDLER_PRI_ANY); + pmc_kld_unload_tag = EVENTHANDLER_REGISTER(kld_unload, pmc_kld_unload, + NULL, EVENTHANDLER_PRI_ANY); + /* initialize logging */ pmclog_initialize(); @@ -4970,6 +4961,8 @@ pmc_cleanup(void) /* deregister event handlers */ EVENTHANDLER_DEREGISTER(process_fork, pmc_fork_tag); EVENTHANDLER_DEREGISTER(process_exit, pmc_exit_tag); + EVENTHANDLER_DEREGISTER(kld_load, pmc_kld_load_tag); + EVENTHANDLER_DEREGISTER(kld_unload, pmc_kld_unload_tag); /* send SIGBUS to all owner threads, free up allocations */ if (pmc_ownerhash) diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 528666c..0ddd21b 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -1016,9 +1016,6 @@ linker_search_symbol_name(caddr_t value, char *buf, u_int buflen, int kern_kldload(struct thread *td, const char *file, int *fileid) { -#ifdef HWPMC_HOOKS - struct pmckern_map_in pkm; -#endif const char *kldname, *modname; linker_file_t lf; int error; @@ -1058,17 +1055,9 @@ kern_kldload(struct thread *td, const char *file, int *fileid) if (fileid != NULL) *fileid = lf->id; - EVENTHANDLER_INVOKE(kld_load, lf); - -#ifdef HWPMC_HOOKS KLD_DOWNGRADE(); - pkm.pm_file = lf->filename; - pkm.pm_address = (uintptr_t) lf->address; - PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm); + EVENTHANDLER_INVOKE(kld_load, lf); KLD_UNLOCK_READ(); -#else - KLD_UNLOCK(); -#endif done: CURVNET_RESTORE(); @@ -1097,10 +1086,10 @@ sys_kldload(struct thread *td, struct kldload_args *uap) int kern_kldunload(struct thread *td, int fileid, int flags) { -#ifdef HWPMC_HOOKS - struct pmckern_map_out pkm; -#endif linker_file_t lf; + char *filename = NULL; + caddr_t address; + size_t size; int error = 0; if ((error = securelevel_gt(td->td_ucred, 0)) != 0) @@ -1115,7 +1104,7 @@ kern_kldunload(struct thread *td, int fileid, int flags) if (lf) { KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); - EVENTHANDLER_INVOKE(kld_unload, lf, &error); + EVENTHANDLER_INVOKE(kld_unload_try, lf, &error); if (error != 0) error = EBUSY; else if (lf->userrefs == 0) { @@ -1126,11 +1115,11 @@ kern_kldunload(struct thread *td, int fileid, int flags) " loaded by the kernel\n"); error = EBUSY; } else { -#ifdef HWPMC_HOOKS - /* Save data needed by hwpmc(4) before unloading. */ - pkm.pm_address = (uintptr_t) lf->address; - pkm.pm_size = lf->size; -#endif + /* Save data needed for the kld_unload callbacks. */ + filename = strdup(lf->filename, M_TEMP); + address = lf->address; + size = lf->size; + lf->userrefs--; error = linker_file_unload(lf, flags); if (error) @@ -1139,16 +1128,14 @@ kern_kldunload(struct thread *td, int fileid, int flags) } else error = ENOENT; -#ifdef HWPMC_HOOKS if (error == 0) { KLD_DOWNGRADE(); - PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm); + EVENTHANDLER_INVOKE(kld_unload, filename, address, size); KLD_UNLOCK_READ(); } else KLD_UNLOCK(); -#else - KLD_UNLOCK(); -#endif + free(filename, M_TEMP); + CURVNET_RESTORE(); return (error); } diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h index a1f9c55..2656877 100644 --- a/sys/sys/eventhandler.h +++ b/sys/sys/eventhandler.h @@ -269,8 +269,11 @@ EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn); /* Kernel linker file load and unload events */ struct linker_file; typedef void (*kld_load_fn)(void *, struct linker_file *); -typedef void (*kld_unload_fn)(void *, struct linker_file *, int *); +typedef void (*kld_unload_fn)(void *, const char *filename, caddr_t addr, + size_t size); +typedef void (*kld_unload_try_fn)(void *, struct linker_file *, int *); EVENTHANDLER_DECLARE(kld_load, kld_load_fn); EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn); +EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn); #endif /* SYS_EVENTHANDLER_H */ diff --git a/sys/sys/pmckern.h b/sys/sys/pmckern.h index e3e18a6..90585de 100644 --- a/sys/sys/pmckern.h +++ b/sys/sys/pmckern.h @@ -51,13 +51,11 @@ #define PMC_FN_CSW_IN 2 #define PMC_FN_CSW_OUT 3 #define PMC_FN_DO_SAMPLES 4 -#define PMC_FN_KLD_LOAD 5 -#define PMC_FN_KLD_UNLOAD 6 -#define PMC_FN_MMAP 7 -#define PMC_FN_MUNMAP 8 -#define PMC_FN_USER_CALLCHAIN 9 -#define PMC_FN_USER_CALLCHAIN_SOFT 10 -#define PMC_FN_SOFT_SAMPLING 11 +#define PMC_FN_MMAP 5 +#define PMC_FN_MUNMAP 6 +#define PMC_FN_USER_CALLCHAIN 7 +#define PMC_FN_USER_CALLCHAIN_SOFT 8 +#define PMC_FN_SOFT_SAMPLING 9 #define PMC_HR 0 /* Hardware ring buffer */ #define PMC_SR 1 /* Software ring buffer */