| 748 | } |
| 749 | |
| 750 | static int |
| 751 | sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse) |
| 752 | { |
| 753 | struct sysctl_oid *p, *tmp; |
| 754 | int error; |
| 755 | |
| 756 | SYSCTL_ASSERT_WLOCKED(); |
| 757 | if (oidp == NULL) |
| 758 | return(EINVAL); |
| 759 | if ((oidp->oid_kind & CTLFLAG_DYN) == 0) { |
| 760 | printf("Warning: can't remove non-dynamic nodes (%s)!\n", |
| 761 | oidp->oid_name); |
| 762 | return (EINVAL); |
| 763 | } |
| 764 | /* |
| 765 | * WARNING: normal method to do this should be through |
| 766 | * sysctl_ctx_free(). Use recursing as the last resort |
| 767 | * method to purge your sysctl tree of leftovers... |
| 768 | * However, if some other code still references these nodes, |
| 769 | * it will panic. |
| 770 | */ |
| 771 | if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { |
| 772 | if (oidp->oid_refcnt == 1) { |
| 773 | SLIST_FOREACH_SAFE(p, |
| 774 | SYSCTL_CHILDREN(oidp), oid_link, tmp) { |
| 775 | if (!recurse) { |
| 776 | printf("Warning: failed attempt to " |
| 777 | "remove oid %s with child %s\n", |
| 778 | oidp->oid_name, p->oid_name); |
| 779 | return (ENOTEMPTY); |
| 780 | } |
| 781 | error = sysctl_remove_oid_locked(p, del, |
| 782 | recurse); |
| 783 | if (error) |
| 784 | return (error); |
| 785 | } |
| 786 | } |
| 787 | } |
| 788 | if (oidp->oid_refcnt > 1 ) { |
| 789 | oidp->oid_refcnt--; |
| 790 | } else { |
| 791 | if (oidp->oid_refcnt == 0) { |
| 792 | printf("Warning: bad oid_refcnt=%u (%s)!\n", |
| 793 | oidp->oid_refcnt, oidp->oid_name); |
| 794 | return (EINVAL); |
| 795 | } |
| 796 | sysctl_unregister_oid(oidp); |
| 797 | if (del) { |
| 798 | /* |
| 799 | * Wait for all threads running the handler to drain. |
| 800 | * This preserves the previous behavior when the |
| 801 | * sysctl lock was held across a handler invocation, |
| 802 | * and is necessary for module unload correctness. |
| 803 | */ |
| 804 | while (oidp->oid_running > 0) { |
| 805 | oidp->oid_kind |= CTLFLAG_DYING; |
| 806 | SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0); |
| 807 | } |
no test coverage detected