1/*- 2 * Copyright (c) 1997 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include "opt_compat.h" 28 29#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1997 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include "opt_compat.h" 28 29#include <sys/cdefs.h>
|
31 32#include <sys/param.h> 33#include <sys/kernel.h> 34#include <sys/systm.h> 35#include <sys/eventhandler.h> 36#include <sys/malloc.h> 37#include <sys/sysproto.h> 38#include <sys/sysent.h> 39#include <sys/proc.h> 40#include <sys/lock.h> 41#include <sys/mutex.h> 42#include <sys/reboot.h> 43#include <sys/sx.h> 44#include <sys/module.h> 45#include <sys/linker.h> 46 47static MALLOC_DEFINE(M_MODULE, "module", "module data structures"); 48 49typedef TAILQ_HEAD(, module) modulelist_t; 50struct module { 51 TAILQ_ENTRY(module) link; /* chain together all modules */ 52 TAILQ_ENTRY(module) flink; /* all modules in a file */ 53 struct linker_file *file; /* file which contains this module */ 54 int refs; /* reference count */ 55 int id; /* unique id number */ 56 char *name; /* module name */ 57 modeventhand_t handler; /* event handler */ 58 void *arg; /* argument for handler */ 59 modspecific_t data; /* module specific data */ 60}; 61 62#define MOD_EVENT(mod, type) (mod)->handler((mod), (type), (mod)->arg) 63 64static modulelist_t modules; 65struct sx modules_sx; 66static int nextid = 1; 67static void module_shutdown(void *, int); 68 69static int 70modevent_nop(module_t mod, int what, void *arg) 71{ 72 73 switch(what) { 74 case MOD_LOAD: 75 return (0); 76 case MOD_UNLOAD: 77 return (EBUSY); 78 default: 79 return (EOPNOTSUPP); 80 } 81} 82 83static void 84module_init(void *arg) 85{ 86 87 sx_init(&modules_sx, "module subsystem sx lock"); 88 TAILQ_INIT(&modules); 89 EVENTHANDLER_REGISTER(shutdown_final, module_shutdown, NULL, 90 SHUTDOWN_PRI_DEFAULT); 91} 92 93SYSINIT(module, SI_SUB_KLD, SI_ORDER_FIRST, module_init, 0); 94 95static void 96module_shutdown(void *arg1, int arg2) 97{ 98 module_t mod; 99 100 if (arg2 & RB_NOSYNC) 101 return; 102 mtx_lock(&Giant); 103 MOD_SLOCK; 104 TAILQ_FOREACH(mod, &modules, link) 105 MOD_EVENT(mod, MOD_SHUTDOWN); 106 MOD_SUNLOCK; 107 mtx_unlock(&Giant); 108} 109 110void 111module_register_init(const void *arg) 112{ 113 const moduledata_t *data = (const moduledata_t *)arg; 114 int error; 115 module_t mod; 116 117 mtx_lock(&Giant); 118 MOD_SLOCK; 119 mod = module_lookupbyname(data->name); 120 if (mod == NULL) 121 panic("module_register_init: module named %s not found\n", 122 data->name); 123 MOD_SUNLOCK; 124 error = MOD_EVENT(mod, MOD_LOAD); 125 if (error) { 126 MOD_EVENT(mod, MOD_UNLOAD); 127 MOD_XLOCK; 128 module_release(mod); 129 MOD_XUNLOCK; 130 printf("module_register_init: MOD_LOAD (%s, %p, %p) error" 131 " %d\n", data->name, (void *)data->evhand, data->priv, 132 error); 133 } else { 134 MOD_XLOCK; 135 if (mod->file) { 136 /* 137 * Once a module is succesfully loaded, move 138 * it to the head of the module list for this 139 * linker file. This resorts the list so that 140 * when the kernel linker iterates over the 141 * modules to unload them, it will unload them 142 * in the reverse order they were loaded. 143 */ 144 TAILQ_REMOVE(&mod->file->modules, mod, flink); 145 TAILQ_INSERT_HEAD(&mod->file->modules, mod, flink); 146 } 147 MOD_XUNLOCK; 148 } 149 mtx_unlock(&Giant); 150} 151 152int 153module_register(const moduledata_t *data, linker_file_t container) 154{ 155 size_t namelen; 156 module_t newmod; 157 158 MOD_XLOCK; 159 newmod = module_lookupbyname(data->name); 160 if (newmod != NULL) { 161 MOD_XUNLOCK; 162 printf("module_register: module %s already exists!\n", 163 data->name); 164 return (EEXIST); 165 } 166 namelen = strlen(data->name) + 1; 167 newmod = malloc(sizeof(struct module) + namelen, M_MODULE, M_WAITOK); 168 if (newmod == NULL) { 169 MOD_XUNLOCK; 170 return (ENOMEM); 171 } 172 newmod->refs = 1; 173 newmod->id = nextid++; 174 newmod->name = (char *)(newmod + 1); 175 strcpy(newmod->name, data->name); 176 newmod->handler = data->evhand ? data->evhand : modevent_nop; 177 newmod->arg = data->priv; 178 bzero(&newmod->data, sizeof(newmod->data)); 179 TAILQ_INSERT_TAIL(&modules, newmod, link); 180 181 if (container) 182 TAILQ_INSERT_TAIL(&container->modules, newmod, flink); 183 newmod->file = container; 184 MOD_XUNLOCK; 185 return (0); 186} 187 188void 189module_reference(module_t mod) 190{ 191 192 MOD_XLOCK_ASSERT; 193 194 MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs)); 195 mod->refs++; 196} 197 198void 199module_release(module_t mod) 200{ 201 202 MOD_XLOCK_ASSERT; 203 204 if (mod->refs <= 0) 205 panic("module_release: bad reference count"); 206 207 MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs)); 208 209 mod->refs--; 210 if (mod->refs == 0) { 211 TAILQ_REMOVE(&modules, mod, link); 212 if (mod->file) 213 TAILQ_REMOVE(&mod->file->modules, mod, flink); 214 free(mod, M_MODULE); 215 } 216} 217 218module_t 219module_lookupbyname(const char *name) 220{ 221 module_t mod; 222 int err; 223 224 MOD_LOCK_ASSERT; 225 226 TAILQ_FOREACH(mod, &modules, link) { 227 err = strcmp(mod->name, name); 228 if (err == 0) 229 return (mod); 230 } 231 return (NULL); 232} 233 234module_t 235module_lookupbyid(int modid) 236{ 237 module_t mod; 238 239 MOD_LOCK_ASSERT; 240 241 TAILQ_FOREACH(mod, &modules, link) 242 if (mod->id == modid) 243 return(mod); 244 return (NULL); 245} 246 247int 248module_quiesce(module_t mod) 249{ 250 int error; 251 252 mtx_lock(&Giant); 253 error = MOD_EVENT(mod, MOD_QUIESCE); 254 mtx_unlock(&Giant); 255 if (error == EOPNOTSUPP || error == EINVAL) 256 error = 0; 257 return (error); 258} 259 260int 261module_unload(module_t mod) 262{ 263 int error; 264 265 mtx_lock(&Giant); 266 error = MOD_EVENT(mod, MOD_UNLOAD); 267 mtx_unlock(&Giant); 268 return (error); 269} 270 271int 272module_getid(module_t mod) 273{ 274 275 MOD_LOCK_ASSERT; 276 return (mod->id); 277} 278 279module_t 280module_getfnext(module_t mod) 281{ 282 283 MOD_LOCK_ASSERT; 284 return (TAILQ_NEXT(mod, flink)); 285} 286 287const char * 288module_getname(module_t mod) 289{ 290 291 MOD_LOCK_ASSERT; 292 return (mod->name); 293} 294 295void 296module_setspecific(module_t mod, modspecific_t *datap) 297{ 298 299 MOD_XLOCK_ASSERT; 300 mod->data = *datap; 301} 302 303linker_file_t 304module_file(module_t mod) 305{ 306 307 return (mod->file); 308} 309 310/* 311 * Syscalls. 312 */ 313int 314modnext(struct thread *td, struct modnext_args *uap) 315{ 316 module_t mod; 317 int error = 0; 318 319 td->td_retval[0] = -1; 320 321 MOD_SLOCK; 322 if (uap->modid == 0) { 323 mod = TAILQ_FIRST(&modules); 324 if (mod) 325 td->td_retval[0] = mod->id; 326 else 327 error = ENOENT; 328 goto done2; 329 } 330 mod = module_lookupbyid(uap->modid); 331 if (mod == NULL) { 332 error = ENOENT; 333 goto done2; 334 } 335 if (TAILQ_NEXT(mod, link)) 336 td->td_retval[0] = TAILQ_NEXT(mod, link)->id; 337 else 338 td->td_retval[0] = 0; 339done2: 340 MOD_SUNLOCK; 341 return (error); 342} 343 344int 345modfnext(struct thread *td, struct modfnext_args *uap) 346{ 347 module_t mod; 348 int error; 349 350 td->td_retval[0] = -1; 351 352 MOD_SLOCK; 353 mod = module_lookupbyid(uap->modid); 354 if (mod == NULL) { 355 error = ENOENT; 356 } else { 357 error = 0; 358 if (TAILQ_NEXT(mod, flink)) 359 td->td_retval[0] = TAILQ_NEXT(mod, flink)->id; 360 else 361 td->td_retval[0] = 0; 362 } 363 MOD_SUNLOCK; 364 return (error); 365} 366 367struct module_stat_v1 { 368 int version; /* set to sizeof(struct module_stat) */ 369 char name[MAXMODNAME]; 370 int refs; 371 int id; 372}; 373 374int 375modstat(struct thread *td, struct modstat_args *uap) 376{ 377 module_t mod; 378 modspecific_t data; 379 int error = 0; 380 int id, namelen, refs, version; 381 struct module_stat *stat; 382 char *name; 383 384 MOD_SLOCK; 385 mod = module_lookupbyid(uap->modid); 386 if (mod == NULL) { 387 MOD_SUNLOCK; 388 return (ENOENT); 389 } 390 id = mod->id; 391 refs = mod->refs; 392 name = mod->name; 393 data = mod->data; 394 MOD_SUNLOCK; 395 stat = uap->stat; 396 397 /* 398 * Check the version of the user's structure. 399 */ 400 if ((error = copyin(&stat->version, &version, sizeof(version))) != 0) 401 return (error); 402 if (version != sizeof(struct module_stat_v1) 403 && version != sizeof(struct module_stat)) 404 return (EINVAL); 405 namelen = strlen(mod->name) + 1; 406 if (namelen > MAXMODNAME) 407 namelen = MAXMODNAME; 408 if ((error = copyout(name, &stat->name[0], namelen)) != 0) 409 return (error); 410 411 if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0) 412 return (error); 413 if ((error = copyout(&id, &stat->id, sizeof(int))) != 0) 414 return (error); 415 416 /* 417 * >v1 stat includes module data. 418 */ 419 if (version == sizeof(struct module_stat)) 420 if ((error = copyout(&data, &stat->data, 421 sizeof(data))) != 0) 422 return (error); 423 td->td_retval[0] = 0; 424 return (error); 425} 426 427int 428modfind(struct thread *td, struct modfind_args *uap) 429{ 430 int error = 0; 431 char name[MAXMODNAME]; 432 module_t mod; 433 434 if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0) 435 return (error); 436 437 MOD_SLOCK; 438 mod = module_lookupbyname(name); 439 if (mod == NULL) 440 error = ENOENT; 441 else 442 td->td_retval[0] = module_getid(mod); 443 MOD_SUNLOCK; 444 return (error); 445} 446 447MODULE_VERSION(kernel, __FreeBSD_version); 448 449#ifdef COMPAT_FREEBSD32 450#include <sys/mount.h> 451#include <sys/socket.h> 452#include <compat/freebsd32/freebsd32_util.h> 453#include <compat/freebsd32/freebsd32.h> 454#include <compat/freebsd32/freebsd32_proto.h> 455 456typedef union modspecific32 { 457 int intval;
| 31 32#include <sys/param.h> 33#include <sys/kernel.h> 34#include <sys/systm.h> 35#include <sys/eventhandler.h> 36#include <sys/malloc.h> 37#include <sys/sysproto.h> 38#include <sys/sysent.h> 39#include <sys/proc.h> 40#include <sys/lock.h> 41#include <sys/mutex.h> 42#include <sys/reboot.h> 43#include <sys/sx.h> 44#include <sys/module.h> 45#include <sys/linker.h> 46 47static MALLOC_DEFINE(M_MODULE, "module", "module data structures"); 48 49typedef TAILQ_HEAD(, module) modulelist_t; 50struct module { 51 TAILQ_ENTRY(module) link; /* chain together all modules */ 52 TAILQ_ENTRY(module) flink; /* all modules in a file */ 53 struct linker_file *file; /* file which contains this module */ 54 int refs; /* reference count */ 55 int id; /* unique id number */ 56 char *name; /* module name */ 57 modeventhand_t handler; /* event handler */ 58 void *arg; /* argument for handler */ 59 modspecific_t data; /* module specific data */ 60}; 61 62#define MOD_EVENT(mod, type) (mod)->handler((mod), (type), (mod)->arg) 63 64static modulelist_t modules; 65struct sx modules_sx; 66static int nextid = 1; 67static void module_shutdown(void *, int); 68 69static int 70modevent_nop(module_t mod, int what, void *arg) 71{ 72 73 switch(what) { 74 case MOD_LOAD: 75 return (0); 76 case MOD_UNLOAD: 77 return (EBUSY); 78 default: 79 return (EOPNOTSUPP); 80 } 81} 82 83static void 84module_init(void *arg) 85{ 86 87 sx_init(&modules_sx, "module subsystem sx lock"); 88 TAILQ_INIT(&modules); 89 EVENTHANDLER_REGISTER(shutdown_final, module_shutdown, NULL, 90 SHUTDOWN_PRI_DEFAULT); 91} 92 93SYSINIT(module, SI_SUB_KLD, SI_ORDER_FIRST, module_init, 0); 94 95static void 96module_shutdown(void *arg1, int arg2) 97{ 98 module_t mod; 99 100 if (arg2 & RB_NOSYNC) 101 return; 102 mtx_lock(&Giant); 103 MOD_SLOCK; 104 TAILQ_FOREACH(mod, &modules, link) 105 MOD_EVENT(mod, MOD_SHUTDOWN); 106 MOD_SUNLOCK; 107 mtx_unlock(&Giant); 108} 109 110void 111module_register_init(const void *arg) 112{ 113 const moduledata_t *data = (const moduledata_t *)arg; 114 int error; 115 module_t mod; 116 117 mtx_lock(&Giant); 118 MOD_SLOCK; 119 mod = module_lookupbyname(data->name); 120 if (mod == NULL) 121 panic("module_register_init: module named %s not found\n", 122 data->name); 123 MOD_SUNLOCK; 124 error = MOD_EVENT(mod, MOD_LOAD); 125 if (error) { 126 MOD_EVENT(mod, MOD_UNLOAD); 127 MOD_XLOCK; 128 module_release(mod); 129 MOD_XUNLOCK; 130 printf("module_register_init: MOD_LOAD (%s, %p, %p) error" 131 " %d\n", data->name, (void *)data->evhand, data->priv, 132 error); 133 } else { 134 MOD_XLOCK; 135 if (mod->file) { 136 /* 137 * Once a module is succesfully loaded, move 138 * it to the head of the module list for this 139 * linker file. This resorts the list so that 140 * when the kernel linker iterates over the 141 * modules to unload them, it will unload them 142 * in the reverse order they were loaded. 143 */ 144 TAILQ_REMOVE(&mod->file->modules, mod, flink); 145 TAILQ_INSERT_HEAD(&mod->file->modules, mod, flink); 146 } 147 MOD_XUNLOCK; 148 } 149 mtx_unlock(&Giant); 150} 151 152int 153module_register(const moduledata_t *data, linker_file_t container) 154{ 155 size_t namelen; 156 module_t newmod; 157 158 MOD_XLOCK; 159 newmod = module_lookupbyname(data->name); 160 if (newmod != NULL) { 161 MOD_XUNLOCK; 162 printf("module_register: module %s already exists!\n", 163 data->name); 164 return (EEXIST); 165 } 166 namelen = strlen(data->name) + 1; 167 newmod = malloc(sizeof(struct module) + namelen, M_MODULE, M_WAITOK); 168 if (newmod == NULL) { 169 MOD_XUNLOCK; 170 return (ENOMEM); 171 } 172 newmod->refs = 1; 173 newmod->id = nextid++; 174 newmod->name = (char *)(newmod + 1); 175 strcpy(newmod->name, data->name); 176 newmod->handler = data->evhand ? data->evhand : modevent_nop; 177 newmod->arg = data->priv; 178 bzero(&newmod->data, sizeof(newmod->data)); 179 TAILQ_INSERT_TAIL(&modules, newmod, link); 180 181 if (container) 182 TAILQ_INSERT_TAIL(&container->modules, newmod, flink); 183 newmod->file = container; 184 MOD_XUNLOCK; 185 return (0); 186} 187 188void 189module_reference(module_t mod) 190{ 191 192 MOD_XLOCK_ASSERT; 193 194 MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs)); 195 mod->refs++; 196} 197 198void 199module_release(module_t mod) 200{ 201 202 MOD_XLOCK_ASSERT; 203 204 if (mod->refs <= 0) 205 panic("module_release: bad reference count"); 206 207 MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs)); 208 209 mod->refs--; 210 if (mod->refs == 0) { 211 TAILQ_REMOVE(&modules, mod, link); 212 if (mod->file) 213 TAILQ_REMOVE(&mod->file->modules, mod, flink); 214 free(mod, M_MODULE); 215 } 216} 217 218module_t 219module_lookupbyname(const char *name) 220{ 221 module_t mod; 222 int err; 223 224 MOD_LOCK_ASSERT; 225 226 TAILQ_FOREACH(mod, &modules, link) { 227 err = strcmp(mod->name, name); 228 if (err == 0) 229 return (mod); 230 } 231 return (NULL); 232} 233 234module_t 235module_lookupbyid(int modid) 236{ 237 module_t mod; 238 239 MOD_LOCK_ASSERT; 240 241 TAILQ_FOREACH(mod, &modules, link) 242 if (mod->id == modid) 243 return(mod); 244 return (NULL); 245} 246 247int 248module_quiesce(module_t mod) 249{ 250 int error; 251 252 mtx_lock(&Giant); 253 error = MOD_EVENT(mod, MOD_QUIESCE); 254 mtx_unlock(&Giant); 255 if (error == EOPNOTSUPP || error == EINVAL) 256 error = 0; 257 return (error); 258} 259 260int 261module_unload(module_t mod) 262{ 263 int error; 264 265 mtx_lock(&Giant); 266 error = MOD_EVENT(mod, MOD_UNLOAD); 267 mtx_unlock(&Giant); 268 return (error); 269} 270 271int 272module_getid(module_t mod) 273{ 274 275 MOD_LOCK_ASSERT; 276 return (mod->id); 277} 278 279module_t 280module_getfnext(module_t mod) 281{ 282 283 MOD_LOCK_ASSERT; 284 return (TAILQ_NEXT(mod, flink)); 285} 286 287const char * 288module_getname(module_t mod) 289{ 290 291 MOD_LOCK_ASSERT; 292 return (mod->name); 293} 294 295void 296module_setspecific(module_t mod, modspecific_t *datap) 297{ 298 299 MOD_XLOCK_ASSERT; 300 mod->data = *datap; 301} 302 303linker_file_t 304module_file(module_t mod) 305{ 306 307 return (mod->file); 308} 309 310/* 311 * Syscalls. 312 */ 313int 314modnext(struct thread *td, struct modnext_args *uap) 315{ 316 module_t mod; 317 int error = 0; 318 319 td->td_retval[0] = -1; 320 321 MOD_SLOCK; 322 if (uap->modid == 0) { 323 mod = TAILQ_FIRST(&modules); 324 if (mod) 325 td->td_retval[0] = mod->id; 326 else 327 error = ENOENT; 328 goto done2; 329 } 330 mod = module_lookupbyid(uap->modid); 331 if (mod == NULL) { 332 error = ENOENT; 333 goto done2; 334 } 335 if (TAILQ_NEXT(mod, link)) 336 td->td_retval[0] = TAILQ_NEXT(mod, link)->id; 337 else 338 td->td_retval[0] = 0; 339done2: 340 MOD_SUNLOCK; 341 return (error); 342} 343 344int 345modfnext(struct thread *td, struct modfnext_args *uap) 346{ 347 module_t mod; 348 int error; 349 350 td->td_retval[0] = -1; 351 352 MOD_SLOCK; 353 mod = module_lookupbyid(uap->modid); 354 if (mod == NULL) { 355 error = ENOENT; 356 } else { 357 error = 0; 358 if (TAILQ_NEXT(mod, flink)) 359 td->td_retval[0] = TAILQ_NEXT(mod, flink)->id; 360 else 361 td->td_retval[0] = 0; 362 } 363 MOD_SUNLOCK; 364 return (error); 365} 366 367struct module_stat_v1 { 368 int version; /* set to sizeof(struct module_stat) */ 369 char name[MAXMODNAME]; 370 int refs; 371 int id; 372}; 373 374int 375modstat(struct thread *td, struct modstat_args *uap) 376{ 377 module_t mod; 378 modspecific_t data; 379 int error = 0; 380 int id, namelen, refs, version; 381 struct module_stat *stat; 382 char *name; 383 384 MOD_SLOCK; 385 mod = module_lookupbyid(uap->modid); 386 if (mod == NULL) { 387 MOD_SUNLOCK; 388 return (ENOENT); 389 } 390 id = mod->id; 391 refs = mod->refs; 392 name = mod->name; 393 data = mod->data; 394 MOD_SUNLOCK; 395 stat = uap->stat; 396 397 /* 398 * Check the version of the user's structure. 399 */ 400 if ((error = copyin(&stat->version, &version, sizeof(version))) != 0) 401 return (error); 402 if (version != sizeof(struct module_stat_v1) 403 && version != sizeof(struct module_stat)) 404 return (EINVAL); 405 namelen = strlen(mod->name) + 1; 406 if (namelen > MAXMODNAME) 407 namelen = MAXMODNAME; 408 if ((error = copyout(name, &stat->name[0], namelen)) != 0) 409 return (error); 410 411 if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0) 412 return (error); 413 if ((error = copyout(&id, &stat->id, sizeof(int))) != 0) 414 return (error); 415 416 /* 417 * >v1 stat includes module data. 418 */ 419 if (version == sizeof(struct module_stat)) 420 if ((error = copyout(&data, &stat->data, 421 sizeof(data))) != 0) 422 return (error); 423 td->td_retval[0] = 0; 424 return (error); 425} 426 427int 428modfind(struct thread *td, struct modfind_args *uap) 429{ 430 int error = 0; 431 char name[MAXMODNAME]; 432 module_t mod; 433 434 if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0) 435 return (error); 436 437 MOD_SLOCK; 438 mod = module_lookupbyname(name); 439 if (mod == NULL) 440 error = ENOENT; 441 else 442 td->td_retval[0] = module_getid(mod); 443 MOD_SUNLOCK; 444 return (error); 445} 446 447MODULE_VERSION(kernel, __FreeBSD_version); 448 449#ifdef COMPAT_FREEBSD32 450#include <sys/mount.h> 451#include <sys/socket.h> 452#include <compat/freebsd32/freebsd32_util.h> 453#include <compat/freebsd32/freebsd32.h> 454#include <compat/freebsd32/freebsd32_proto.h> 455 456typedef union modspecific32 { 457 int intval;
|
461} modspecific32_t; 462 463struct module_stat32 { 464 int version; 465 char name[MAXMODNAME]; 466 int refs; 467 int id; 468 modspecific32_t data; 469}; 470 471int 472freebsd32_modstat(struct thread *td, struct freebsd32_modstat_args *uap) 473{ 474 module_t mod; 475 modspecific32_t data32; 476 int error = 0; 477 int id, namelen, refs, version; 478 struct module_stat32 *stat32; 479 char *name; 480 481 MOD_SLOCK; 482 mod = module_lookupbyid(uap->modid); 483 if (mod == NULL) { 484 MOD_SUNLOCK; 485 return (ENOENT); 486 } 487 488 id = mod->id; 489 refs = mod->refs; 490 name = mod->name; 491 CP(mod->data, data32, intval); 492 CP(mod->data, data32, uintval); 493 CP(mod->data, data32, longval); 494 CP(mod->data, data32, ulongval); 495 MOD_SUNLOCK; 496 stat32 = uap->stat; 497 498 if ((error = copyin(&stat32->version, &version, sizeof(version))) != 0) 499 return (error); 500 if (version != sizeof(struct module_stat_v1) 501 && version != sizeof(struct module_stat32)) 502 return (EINVAL); 503 namelen = strlen(mod->name) + 1; 504 if (namelen > MAXMODNAME) 505 namelen = MAXMODNAME; 506 if ((error = copyout(name, &stat32->name[0], namelen)) != 0) 507 return (error); 508 509 if ((error = copyout(&refs, &stat32->refs, sizeof(int))) != 0) 510 return (error); 511 if ((error = copyout(&id, &stat32->id, sizeof(int))) != 0) 512 return (error); 513 514 /* 515 * >v1 stat includes module data. 516 */ 517 if (version == sizeof(struct module_stat32)) 518 if ((error = copyout(&data32, &stat32->data, 519 sizeof(data32))) != 0) 520 return (error); 521 td->td_retval[0] = 0; 522 return (error); 523} 524#endif
| 461} modspecific32_t; 462 463struct module_stat32 { 464 int version; 465 char name[MAXMODNAME]; 466 int refs; 467 int id; 468 modspecific32_t data; 469}; 470 471int 472freebsd32_modstat(struct thread *td, struct freebsd32_modstat_args *uap) 473{ 474 module_t mod; 475 modspecific32_t data32; 476 int error = 0; 477 int id, namelen, refs, version; 478 struct module_stat32 *stat32; 479 char *name; 480 481 MOD_SLOCK; 482 mod = module_lookupbyid(uap->modid); 483 if (mod == NULL) { 484 MOD_SUNLOCK; 485 return (ENOENT); 486 } 487 488 id = mod->id; 489 refs = mod->refs; 490 name = mod->name; 491 CP(mod->data, data32, intval); 492 CP(mod->data, data32, uintval); 493 CP(mod->data, data32, longval); 494 CP(mod->data, data32, ulongval); 495 MOD_SUNLOCK; 496 stat32 = uap->stat; 497 498 if ((error = copyin(&stat32->version, &version, sizeof(version))) != 0) 499 return (error); 500 if (version != sizeof(struct module_stat_v1) 501 && version != sizeof(struct module_stat32)) 502 return (EINVAL); 503 namelen = strlen(mod->name) + 1; 504 if (namelen > MAXMODNAME) 505 namelen = MAXMODNAME; 506 if ((error = copyout(name, &stat32->name[0], namelen)) != 0) 507 return (error); 508 509 if ((error = copyout(&refs, &stat32->refs, sizeof(int))) != 0) 510 return (error); 511 if ((error = copyout(&id, &stat32->id, sizeof(int))) != 0) 512 return (error); 513 514 /* 515 * >v1 stat includes module data. 516 */ 517 if (version == sizeof(struct module_stat32)) 518 if ((error = copyout(&data32, &stat32->data, 519 sizeof(data32))) != 0) 520 return (error); 521 td->td_retval[0] = 0; 522 return (error); 523} 524#endif
|