| 632 | } |
| 633 | |
| 634 | int |
| 635 | linker_file_unload(linker_file_t file, int flags) |
| 636 | { |
| 637 | module_t mod, next; |
| 638 | modlist_t ml, nextml; |
| 639 | struct common_symbol *cp; |
| 640 | int error, i; |
| 641 | |
| 642 | /* Refuse to unload modules if securelevel raised. */ |
| 643 | if (prison0.pr_securelevel > 0) |
| 644 | return (EPERM); |
| 645 | |
| 646 | sx_assert(&kld_sx, SA_XLOCKED); |
| 647 | KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs)); |
| 648 | |
| 649 | /* Easy case of just dropping a reference. */ |
| 650 | if (file->refs > 1) { |
| 651 | file->refs--; |
| 652 | return (0); |
| 653 | } |
| 654 | |
| 655 | /* Give eventhandlers a chance to prevent the unload. */ |
| 656 | error = 0; |
| 657 | EVENTHANDLER_INVOKE(kld_unload_try, file, &error); |
| 658 | if (error != 0) |
| 659 | return (EBUSY); |
| 660 | |
| 661 | KLD_DPF(FILE, ("linker_file_unload: file is unloading," |
| 662 | " informing modules\n")); |
| 663 | |
| 664 | /* |
| 665 | * Quiesce all the modules to give them a chance to veto the unload. |
| 666 | */ |
| 667 | MOD_SLOCK; |
| 668 | for (mod = TAILQ_FIRST(&file->modules); mod; |
| 669 | mod = module_getfnext(mod)) { |
| 670 | error = module_quiesce(mod); |
| 671 | if (error != 0 && flags != LINKER_UNLOAD_FORCE) { |
| 672 | KLD_DPF(FILE, ("linker_file_unload: module %s" |
| 673 | " vetoed unload\n", module_getname(mod))); |
| 674 | /* |
| 675 | * XXX: Do we need to tell all the quiesced modules |
| 676 | * that they can resume work now via a new module |
| 677 | * event? |
| 678 | */ |
| 679 | MOD_SUNLOCK; |
| 680 | return (error); |
| 681 | } |
| 682 | } |
| 683 | MOD_SUNLOCK; |
| 684 | |
| 685 | /* |
| 686 | * Inform any modules associated with this file that they are |
| 687 | * being unloaded. |
| 688 | */ |
| 689 | MOD_XLOCK; |
| 690 | for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) { |
| 691 | next = module_getfnext(mod); |
no test coverage detected