xref: /freebsd/sys/kern/kern_module.c (revision e024f583de7e35e5042c8ad545f950b1acf0007b)
1cea6c86cSDoug Rabson /*-
2cea6c86cSDoug Rabson  * Copyright (c) 1997 Doug Rabson
3cea6c86cSDoug Rabson  * All rights reserved.
4cea6c86cSDoug Rabson  *
5cea6c86cSDoug Rabson  * Redistribution and use in source and binary forms, with or without
6cea6c86cSDoug Rabson  * modification, are permitted provided that the following conditions
7cea6c86cSDoug Rabson  * are met:
8cea6c86cSDoug Rabson  * 1. Redistributions of source code must retain the above copyright
9cea6c86cSDoug Rabson  *    notice, this list of conditions and the following disclaimer.
10cea6c86cSDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
11cea6c86cSDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
12cea6c86cSDoug Rabson  *    documentation and/or other materials provided with the distribution.
13cea6c86cSDoug Rabson  *
14cea6c86cSDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15cea6c86cSDoug Rabson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16cea6c86cSDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17cea6c86cSDoug Rabson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18cea6c86cSDoug Rabson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19cea6c86cSDoug Rabson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20cea6c86cSDoug Rabson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21cea6c86cSDoug Rabson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22cea6c86cSDoug Rabson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23cea6c86cSDoug Rabson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24cea6c86cSDoug Rabson  * SUCH DAMAGE.
25cea6c86cSDoug Rabson  *
26c3aac50fSPeter Wemm  * $FreeBSD$
27cea6c86cSDoug Rabson  */
28cea6c86cSDoug Rabson 
29cea6c86cSDoug Rabson #include <sys/param.h>
30cea6c86cSDoug Rabson #include <sys/kernel.h>
31cea6c86cSDoug Rabson #include <sys/systm.h>
32fcb893a8SMike Smith #include <sys/eventhandler.h>
33cea6c86cSDoug Rabson #include <sys/malloc.h>
34cea6c86cSDoug Rabson #include <sys/sysproto.h>
35cea6c86cSDoug Rabson #include <sys/sysent.h>
36cb226aaaSPoul-Henning Kamp #include <sys/proc.h>
37835a82eeSMatthew Dillon #include <sys/lock.h>
38835a82eeSMatthew Dillon #include <sys/mutex.h>
399b3851e9SAndrew R. Reiter #include <sys/sx.h>
409b3851e9SAndrew R. Reiter #include <sys/module.h>
419b3851e9SAndrew R. Reiter #include <sys/linker.h>
42cea6c86cSDoug Rabson 
43959b7375SPoul-Henning Kamp static MALLOC_DEFINE(M_MODULE, "module", "module data structures");
44cea6c86cSDoug Rabson 
45e3975643SJake Burkholder typedef TAILQ_HEAD(, module) modulelist_t;
46cea6c86cSDoug Rabson struct module {
47e3975643SJake Burkholder 	TAILQ_ENTRY(module)	link;	/* chain together all modules */
48e3975643SJake Burkholder 	TAILQ_ENTRY(module)	flink;	/* all modules in a file */
49cea6c86cSDoug Rabson 	struct linker_file	*file;	/* file which contains this module */
50cea6c86cSDoug Rabson 	int			refs;	/* reference count */
51cea6c86cSDoug Rabson 	int 			id;	/* unique id number */
52cea6c86cSDoug Rabson 	char 			*name;	/* module name */
53cea6c86cSDoug Rabson 	modeventhand_t 		handler;	/* event handler */
54cea6c86cSDoug Rabson 	void 			*arg;	/* argument for handler */
55a35261efSDoug Rabson 	modspecific_t 		data;	/* module specific data */
56cea6c86cSDoug Rabson };
57cea6c86cSDoug Rabson 
58cea6c86cSDoug Rabson #define MOD_EVENT(mod, type)	(mod)->handler((mod), (type), (mod)->arg)
59cea6c86cSDoug Rabson 
60cea6c86cSDoug Rabson static modulelist_t modules;
619b3851e9SAndrew R. Reiter struct sx modules_sx;
62cea6c86cSDoug Rabson static int nextid = 1;
63fcb893a8SMike Smith static void module_shutdown(void *, int);
64cea6c86cSDoug Rabson 
65845ccef4SPeter Wemm static int
66845ccef4SPeter Wemm modevent_nop(module_t mod, int what, void *arg)
67845ccef4SPeter Wemm {
68b65420f9SAndrew R. Reiter 	return (0);
69845ccef4SPeter Wemm }
70845ccef4SPeter Wemm 
71cea6c86cSDoug Rabson static void
72cea6c86cSDoug Rabson module_init(void *arg)
73cea6c86cSDoug Rabson {
74287698b4SAndrew R. Reiter 
759b3851e9SAndrew R. Reiter 	sx_init(&modules_sx, "module subsystem sx lock");
76cea6c86cSDoug Rabson 	TAILQ_INIT(&modules);
77fcb893a8SMike Smith 	EVENTHANDLER_REGISTER(shutdown_post_sync, module_shutdown, NULL,
78fcb893a8SMike Smith 	    SHUTDOWN_PRI_DEFAULT);
79cea6c86cSDoug Rabson }
80cea6c86cSDoug Rabson 
81287698b4SAndrew R. Reiter SYSINIT(module, SI_SUB_KLD, SI_ORDER_FIRST, module_init, 0)
82cea6c86cSDoug Rabson 
83cea6c86cSDoug Rabson static void
84fcb893a8SMike Smith module_shutdown(void *arg1, int arg2)
85cea6c86cSDoug Rabson {
86cea6c86cSDoug Rabson 	module_t mod;
87cea6c86cSDoug Rabson 
889b3851e9SAndrew R. Reiter 	MOD_SLOCK;
89fc2ffbe6SPoul-Henning Kamp 	TAILQ_FOREACH(mod, &modules, link)
90cea6c86cSDoug Rabson 		MOD_EVENT(mod, MOD_SHUTDOWN);
919b3851e9SAndrew R. Reiter 	MOD_SUNLOCK;
92cea6c86cSDoug Rabson }
93cea6c86cSDoug Rabson 
94cea6c86cSDoug Rabson void
953cfc69e6SMatthew Dillon module_register_init(const void *arg)
96cea6c86cSDoug Rabson {
973cfc69e6SMatthew Dillon 	const moduledata_t *data = (const moduledata_t *)arg;
98cea6c86cSDoug Rabson 	int error;
99b5b15c3fSPeter Wemm 	module_t mod;
100cea6c86cSDoug Rabson 
1019b3851e9SAndrew R. Reiter 	MOD_SLOCK;
102b5b15c3fSPeter Wemm 	mod = module_lookupbyname(data->name);
103b5b15c3fSPeter Wemm 	if (mod == NULL)
104287698b4SAndrew R. Reiter 		panic("module_register_init: module named %s not found\n",
105287698b4SAndrew R. Reiter 		    data->name);
1069b3851e9SAndrew R. Reiter 	MOD_SUNLOCK;
107b5b15c3fSPeter Wemm 	error = MOD_EVENT(mod, MOD_LOAD);
108b5b15c3fSPeter Wemm 	if (error) {
109b5b15c3fSPeter Wemm 		MOD_EVENT(mod, MOD_UNLOAD);
1109b3851e9SAndrew R. Reiter 		MOD_XLOCK;
111b5b15c3fSPeter Wemm 		module_release(mod);
1129b3851e9SAndrew R. Reiter 		MOD_XUNLOCK;
113bd47bef5SPeter Wemm 		printf("module_register_init: MOD_LOAD (%s, %p, %p) error"
114bd47bef5SPeter Wemm 		    " %d\n", data->name, (void *)data->evhand, data->priv,
115287698b4SAndrew R. Reiter 		    error);
116cea6c86cSDoug Rabson 	}
117b5b15c3fSPeter Wemm }
118cea6c86cSDoug Rabson 
119cea6c86cSDoug Rabson int
120b5b15c3fSPeter Wemm module_register(const moduledata_t *data, linker_file_t container)
121cea6c86cSDoug Rabson {
122cea6c86cSDoug Rabson 	size_t namelen;
123cea6c86cSDoug Rabson 	module_t newmod;
124cea6c86cSDoug Rabson 
1259b3851e9SAndrew R. Reiter 	MOD_SLOCK;
126b5b15c3fSPeter Wemm 	newmod = module_lookupbyname(data->name);
127b5b15c3fSPeter Wemm 	if (newmod != NULL) {
1289b3851e9SAndrew R. Reiter 		MOD_SUNLOCK;
129287698b4SAndrew R. Reiter 		printf("module_register: module %s already exists!\n",
130287698b4SAndrew R. Reiter 		    data->name);
131b65420f9SAndrew R. Reiter 		return (EEXIST);
132b5b15c3fSPeter Wemm 	}
1339b3851e9SAndrew R. Reiter 	MOD_SUNLOCK;
134b5b15c3fSPeter Wemm 	namelen = strlen(data->name) + 1;
135287698b4SAndrew R. Reiter 	newmod = malloc(sizeof(struct module) + namelen, M_MODULE, M_WAITOK);
136287698b4SAndrew R. Reiter 	if (newmod == NULL)
137b65420f9SAndrew R. Reiter 		return (ENOMEM);
1389b3851e9SAndrew R. Reiter 	MOD_XLOCK;
139cea6c86cSDoug Rabson 	newmod->refs = 1;
140cea6c86cSDoug Rabson 	newmod->id = nextid++;
141cea6c86cSDoug Rabson 	newmod->name = (char *)(newmod + 1);
142b5b15c3fSPeter Wemm 	strcpy(newmod->name, data->name);
143845ccef4SPeter Wemm 	newmod->handler = data->evhand ? data->evhand : modevent_nop;
144b5b15c3fSPeter Wemm 	newmod->arg = data->priv;
145a35261efSDoug Rabson 	bzero(&newmod->data, sizeof(newmod->data));
146cea6c86cSDoug Rabson 	TAILQ_INSERT_TAIL(&modules, newmod, link);
147cea6c86cSDoug Rabson 
148b5b15c3fSPeter Wemm 	if (container)
149f3b0d442SPeter Wemm 		TAILQ_INSERT_TAIL(&container->modules, newmod, flink);
1501d23cba9SPeter Wemm 	newmod->file = container;
1519b3851e9SAndrew R. Reiter 	MOD_XUNLOCK;
152b65420f9SAndrew R. Reiter 	return (0);
153cea6c86cSDoug Rabson }
154cea6c86cSDoug Rabson 
155cea6c86cSDoug Rabson void
156cea6c86cSDoug Rabson module_reference(module_t mod)
157cea6c86cSDoug Rabson {
158cea6c86cSDoug Rabson 
1599b3851e9SAndrew R. Reiter 	MOD_XLOCK_ASSERT;
1609b3851e9SAndrew R. Reiter 
161287698b4SAndrew R. Reiter 	MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs));
162cea6c86cSDoug Rabson 	mod->refs++;
163cea6c86cSDoug Rabson }
164cea6c86cSDoug Rabson 
165cea6c86cSDoug Rabson void
166cea6c86cSDoug Rabson module_release(module_t mod)
167cea6c86cSDoug Rabson {
168287698b4SAndrew R. Reiter 
1699b3851e9SAndrew R. Reiter 	MOD_XLOCK_ASSERT;
1709b3851e9SAndrew R. Reiter 
171cea6c86cSDoug Rabson 	if (mod->refs <= 0)
172cea6c86cSDoug Rabson 		panic("module_release: bad reference count");
173cea6c86cSDoug Rabson 
174cea6c86cSDoug Rabson 	MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs));
175cea6c86cSDoug Rabson 
176cea6c86cSDoug Rabson 	mod->refs--;
177cea6c86cSDoug Rabson 	if (mod->refs == 0) {
178cea6c86cSDoug Rabson 		TAILQ_REMOVE(&modules, mod, link);
179287698b4SAndrew R. Reiter 		if (mod->file)
180cea6c86cSDoug Rabson 			TAILQ_REMOVE(&mod->file->modules, mod, flink);
1819b3851e9SAndrew R. Reiter 		MOD_XUNLOCK;
182cea6c86cSDoug Rabson 		free(mod, M_MODULE);
1839b3851e9SAndrew R. Reiter 		MOD_XLOCK;
184cea6c86cSDoug Rabson 	}
185cea6c86cSDoug Rabson }
186cea6c86cSDoug Rabson 
187cea6c86cSDoug Rabson module_t
188cea6c86cSDoug Rabson module_lookupbyname(const char *name)
189cea6c86cSDoug Rabson {
190cea6c86cSDoug Rabson 	module_t mod;
191287698b4SAndrew R. Reiter 	int err;
192cea6c86cSDoug Rabson 
1939b3851e9SAndrew R. Reiter 	MOD_LOCK_ASSERT;
1949b3851e9SAndrew R. Reiter 
195fc2ffbe6SPoul-Henning Kamp 	TAILQ_FOREACH(mod, &modules, link) {
196287698b4SAndrew R. Reiter 		err = strcmp(mod->name, name);
197287698b4SAndrew R. Reiter 		if (err == 0)
198b65420f9SAndrew R. Reiter 			return (mod);
199cea6c86cSDoug Rabson 	}
200b65420f9SAndrew R. Reiter 	return (NULL);
201cea6c86cSDoug Rabson }
202cea6c86cSDoug Rabson 
203cea6c86cSDoug Rabson module_t
204cea6c86cSDoug Rabson module_lookupbyid(int modid)
205cea6c86cSDoug Rabson {
206cea6c86cSDoug Rabson         module_t mod;
207cea6c86cSDoug Rabson 
2089b3851e9SAndrew R. Reiter         MOD_LOCK_ASSERT;
2099b3851e9SAndrew R. Reiter 
2109b3851e9SAndrew R. Reiter         TAILQ_FOREACH(mod, &modules, link)
211cea6c86cSDoug Rabson                 if (mod->id == modid)
212b65420f9SAndrew R. Reiter                         return(mod);
213b65420f9SAndrew R. Reiter         return (NULL);
214cea6c86cSDoug Rabson }
215cea6c86cSDoug Rabson 
216cea6c86cSDoug Rabson int
217cea6c86cSDoug Rabson module_unload(module_t mod)
218cea6c86cSDoug Rabson {
219287698b4SAndrew R. Reiter 
220b65420f9SAndrew R. Reiter         return (MOD_EVENT(mod, MOD_UNLOAD));
221cea6c86cSDoug Rabson }
222cea6c86cSDoug Rabson 
223cea6c86cSDoug Rabson int
224cea6c86cSDoug Rabson module_getid(module_t mod)
225cea6c86cSDoug Rabson {
226287698b4SAndrew R. Reiter 
2279b3851e9SAndrew R. Reiter 	MOD_LOCK_ASSERT;
228b65420f9SAndrew R. Reiter 	return (mod->id);
229cea6c86cSDoug Rabson }
230cea6c86cSDoug Rabson 
231cea6c86cSDoug Rabson module_t
232cea6c86cSDoug Rabson module_getfnext(module_t mod)
233cea6c86cSDoug Rabson {
234287698b4SAndrew R. Reiter 
2359b3851e9SAndrew R. Reiter 	MOD_LOCK_ASSERT;
236b65420f9SAndrew R. Reiter 	return (TAILQ_NEXT(mod, flink));
237cea6c86cSDoug Rabson }
238cea6c86cSDoug Rabson 
239a35261efSDoug Rabson void
240a35261efSDoug Rabson module_setspecific(module_t mod, modspecific_t *datap)
241a35261efSDoug Rabson {
242287698b4SAndrew R. Reiter 
2439b3851e9SAndrew R. Reiter 	MOD_XLOCK_ASSERT;
244a35261efSDoug Rabson 	mod->data = *datap;
245a35261efSDoug Rabson }
246a35261efSDoug Rabson 
247cea6c86cSDoug Rabson /*
248cea6c86cSDoug Rabson  * Syscalls.
249cea6c86cSDoug Rabson  */
250835a82eeSMatthew Dillon /*
251835a82eeSMatthew Dillon  * MPSAFE
252835a82eeSMatthew Dillon  */
253cea6c86cSDoug Rabson int
254b40ce416SJulian Elischer modnext(struct thread *td, struct modnext_args *uap)
255cea6c86cSDoug Rabson {
256cea6c86cSDoug Rabson 	module_t mod;
257835a82eeSMatthew Dillon 	int error = 0;
258835a82eeSMatthew Dillon 
259b40ce416SJulian Elischer 	td->td_retval[0] = -1;
260e024f583SAndrew R. Reiter 
2619b3851e9SAndrew R. Reiter 	MOD_SLOCK;
262cea6c86cSDoug Rabson 	if (SCARG(uap, modid) == 0) {
263cea6c86cSDoug Rabson 		mod = TAILQ_FIRST(&modules);
264835a82eeSMatthew Dillon 		if (mod)
265b40ce416SJulian Elischer 			td->td_retval[0] = mod->id;
266835a82eeSMatthew Dillon 		else
267835a82eeSMatthew Dillon 			error = ENOENT;
268835a82eeSMatthew Dillon 		goto done2;
269cea6c86cSDoug Rabson 	}
270cea6c86cSDoug Rabson 	mod = module_lookupbyid(SCARG(uap, modid));
271835a82eeSMatthew Dillon 	if (mod == NULL) {
272835a82eeSMatthew Dillon 		error = ENOENT;
273835a82eeSMatthew Dillon 		goto done2;
274835a82eeSMatthew Dillon 	}
275cea6c86cSDoug Rabson 	if (TAILQ_NEXT(mod, link))
276b40ce416SJulian Elischer 		td->td_retval[0] = TAILQ_NEXT(mod, link)->id;
277cea6c86cSDoug Rabson 	else
278b40ce416SJulian Elischer 		td->td_retval[0] = 0;
279835a82eeSMatthew Dillon done2:
2809b3851e9SAndrew R. Reiter 	MOD_SUNLOCK;
281835a82eeSMatthew Dillon 	return (error);
282cea6c86cSDoug Rabson }
283cea6c86cSDoug Rabson 
284835a82eeSMatthew Dillon /*
285835a82eeSMatthew Dillon  * MPSAFE
286835a82eeSMatthew Dillon  */
287cea6c86cSDoug Rabson int
288b40ce416SJulian Elischer modfnext(struct thread *td, struct modfnext_args *uap)
289cea6c86cSDoug Rabson {
290cea6c86cSDoug Rabson 	module_t mod;
291835a82eeSMatthew Dillon 	int error;
292cea6c86cSDoug Rabson 
293b40ce416SJulian Elischer 	td->td_retval[0] = -1;
294cea6c86cSDoug Rabson 
2959b3851e9SAndrew R. Reiter 	MOD_SLOCK;
296835a82eeSMatthew Dillon 	mod = module_lookupbyid(SCARG(uap, modid));
297835a82eeSMatthew Dillon 	if (mod == NULL) {
298835a82eeSMatthew Dillon 		error = ENOENT;
299835a82eeSMatthew Dillon 	} else {
300835a82eeSMatthew Dillon 		error = 0;
301cea6c86cSDoug Rabson 		if (TAILQ_NEXT(mod, flink))
302b40ce416SJulian Elischer 			td->td_retval[0] = TAILQ_NEXT(mod, flink)->id;
303cea6c86cSDoug Rabson 		else
304b40ce416SJulian Elischer 			td->td_retval[0] = 0;
305835a82eeSMatthew Dillon 	}
3069b3851e9SAndrew R. Reiter 	MOD_SUNLOCK;
307835a82eeSMatthew Dillon 	return (error);
308cea6c86cSDoug Rabson }
309cea6c86cSDoug Rabson 
310a35261efSDoug Rabson struct module_stat_v1 {
311a35261efSDoug Rabson 	int	version;		/* set to sizeof(struct module_stat) */
312a35261efSDoug Rabson 	char	name[MAXMODNAME];
313a35261efSDoug Rabson 	int	refs;
314a35261efSDoug Rabson 	int	id;
315a35261efSDoug Rabson };
316a35261efSDoug Rabson 
317835a82eeSMatthew Dillon /*
318835a82eeSMatthew Dillon  * MPSAFE
319835a82eeSMatthew Dillon  */
320cea6c86cSDoug Rabson int
321b40ce416SJulian Elischer modstat(struct thread *td, struct modstat_args *uap)
322cea6c86cSDoug Rabson {
323cea6c86cSDoug Rabson 	module_t mod;
3249b3851e9SAndrew R. Reiter 	modspecific_t data;
325cea6c86cSDoug Rabson 	int error = 0;
3269b3851e9SAndrew R. Reiter 	int id, namelen, refs, version;
327cea6c86cSDoug Rabson 	struct module_stat *stat;
3289b3851e9SAndrew R. Reiter 	char *name;
329cea6c86cSDoug Rabson 
3309b3851e9SAndrew R. Reiter 	MOD_SLOCK;
331cea6c86cSDoug Rabson 	mod = module_lookupbyid(SCARG(uap, modid));
332835a82eeSMatthew Dillon 	if (mod == NULL) {
3339b3851e9SAndrew R. Reiter 		MOD_SUNLOCK;
334e024f583SAndrew R. Reiter 		return (ENOENT);
335835a82eeSMatthew Dillon 	}
3369b3851e9SAndrew R. Reiter 	id = mod->id;
3379b3851e9SAndrew R. Reiter 	refs = mod->refs;
3389b3851e9SAndrew R. Reiter 	name = mod->name;
3399b3851e9SAndrew R. Reiter 	data = mod->data;
3409b3851e9SAndrew R. Reiter 	MOD_SUNLOCK;
341cea6c86cSDoug Rabson 	stat = SCARG(uap, stat);
342cea6c86cSDoug Rabson 
343cea6c86cSDoug Rabson 	/*
344cea6c86cSDoug Rabson 	 * Check the version of the user's structure.
345cea6c86cSDoug Rabson 	 */
346d254af07SMatthew Dillon 	if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
347e024f583SAndrew R. Reiter 		return (error);
348a35261efSDoug Rabson 	if (version != sizeof(struct module_stat_v1)
349e024f583SAndrew R. Reiter 	    && version != sizeof(struct module_stat))
350e024f583SAndrew R. Reiter 		return (EINVAL);
351cea6c86cSDoug Rabson 	namelen = strlen(mod->name) + 1;
352cea6c86cSDoug Rabson 	if (namelen > MAXMODNAME)
353cea6c86cSDoug Rabson 		namelen = MAXMODNAME;
3549b3851e9SAndrew R. Reiter 	if ((error = copyout(name, &stat->name[0], namelen)) != 0)
355e024f583SAndrew R. Reiter 		return (error);
356cea6c86cSDoug Rabson 
3579b3851e9SAndrew R. Reiter 	if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0)
358e024f583SAndrew R. Reiter 		return (error);
3599b3851e9SAndrew R. Reiter 	if ((error = copyout(&id, &stat->id, sizeof(int))) != 0)
360e024f583SAndrew R. Reiter 		return (error);
361cea6c86cSDoug Rabson 
362a35261efSDoug Rabson 	/*
363a35261efSDoug Rabson 	 * >v1 stat includes module data.
364a35261efSDoug Rabson 	 */
365e024f583SAndrew R. Reiter 	if (version == sizeof(struct module_stat))
3669b3851e9SAndrew R. Reiter 		if ((error = copyout(&data, &stat->data,
3679b3851e9SAndrew R. Reiter 		    sizeof(data))) != 0)
368e024f583SAndrew R. Reiter 			return (error);
369b40ce416SJulian Elischer 	td->td_retval[0] = 0;
370b65420f9SAndrew R. Reiter 	return (error);
371cea6c86cSDoug Rabson }
372cea6c86cSDoug Rabson 
373835a82eeSMatthew Dillon /*
374835a82eeSMatthew Dillon  * MPSAFE
375835a82eeSMatthew Dillon  */
376cea6c86cSDoug Rabson int
377b40ce416SJulian Elischer modfind(struct thread *td, struct modfind_args *uap)
378cea6c86cSDoug Rabson {
379cea6c86cSDoug Rabson 	int error = 0;
380cea6c86cSDoug Rabson 	char name[MAXMODNAME];
381cea6c86cSDoug Rabson 	module_t mod;
382cea6c86cSDoug Rabson 
383d254af07SMatthew Dillon 	if ((error = copyinstr(SCARG(uap, name), name, sizeof name, 0)) != 0)
384e024f583SAndrew R. Reiter 		return (error);
385cea6c86cSDoug Rabson 
3869b3851e9SAndrew R. Reiter 	MOD_SLOCK;
387cea6c86cSDoug Rabson 	mod = module_lookupbyname(name);
388835a82eeSMatthew Dillon 	if (mod == NULL)
389cea6c86cSDoug Rabson 		error = ENOENT;
390cea6c86cSDoug Rabson 	else
3919b3851e9SAndrew R. Reiter 		td->td_retval[0] = module_getid(mod);
3929b3851e9SAndrew R. Reiter 	MOD_SUNLOCK;
393b65420f9SAndrew R. Reiter 	return (error);
394cea6c86cSDoug Rabson }
395