git: 7b40b00fad16 - main - ifnet: merge ifindex_alloc(), ifnet_setbyindex(), if_grow() and call magic
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 06 Dec 2021 17:32:48 UTC
The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=7b40b00fad1606eaa98a7b116ba8651221d55f62 commit 7b40b00fad1606eaa98a7b116ba8651221d55f62 Author: Gleb Smirnoff <glebius@FreeBSD.org> AuthorDate: 2021-12-04 17:49:35 +0000 Commit: Gleb Smirnoff <glebius@FreeBSD.org> CommitDate: 2021-12-06 17:32:31 +0000 ifnet: merge ifindex_alloc(), ifnet_setbyindex(), if_grow() and call magic Now it is possible to just merge all this complexity into single linear function. Note that IFNET_WLOCK() is a sleepable lock, so we can M_WAITOK and epoch_wait_preempt(). Reviewed by: melifaro, bz, kp Differential revision: https://reviews.freebsd.org/D33262 --- sys/net/if.c | 95 ++++++++++++++---------------------------------------------- 1 file changed, 21 insertions(+), 74 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index 079ad734812b..ad6d0bcf827a 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -273,7 +273,6 @@ struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL; static void if_attachdomain(void *); static void if_attachdomain1(struct ifnet *); static int ifconf(u_long, caddr_t); -static void *if_grow(void); static void if_input_default(struct ifnet *, struct mbuf *); static int if_requestencap_default(struct ifnet *, struct if_encap_req *); static void if_route(struct ifnet *, int flag, int fam); @@ -369,15 +368,14 @@ ifnet_byindex_ref(u_short idx) } /* - * Allocate an ifindex array entry; return 0 on success or an error on - * failure. + * Allocate an ifindex array entry. */ -static u_short -ifindex_alloc(void **old) +static void +ifindex_alloc(struct ifnet *ifp) { u_short idx; - IFNET_WLOCK_ASSERT(); + IFNET_WLOCK(); /* * Try to find an empty slot below V_if_index. If we fail, take the * next slot. @@ -389,12 +387,24 @@ ifindex_alloc(void **old) /* Catch if_index overflow. */ if (idx >= V_if_indexlim) { - *old = if_grow(); - return (USHRT_MAX); + struct ifnet **new, **old; + int newlim; + + newlim = V_if_indexlim * 2; + new = malloc(newlim * sizeof(*new), M_IFNET, M_WAITOK | M_ZERO); + memcpy(new, V_ifindex_table, V_if_indexlim * sizeof(*new)); + old = V_ifindex_table; + ck_pr_store_ptr(&V_ifindex_table, new); + V_if_indexlim = newlim; + epoch_wait_preempt(net_epoch_preempt); + free(old, M_IFNET); } if (idx > V_if_index) V_if_index = idx; - return (idx); + + ifp->if_index = idx; + ck_pr_store_ptr(&V_ifindex_table[idx], ifp); + IFNET_WUNLOCK(); } static void @@ -409,14 +419,6 @@ ifindex_free(u_short idx) V_if_index--; } -static void -ifnet_setbyindex(u_short idx, struct ifnet *ifp) -{ - - ifp->if_index = idx; - ck_pr_store_ptr(&V_ifindex_table[idx], ifp); -} - struct ifaddr * ifaddr_byindex(u_short idx) { @@ -549,34 +551,6 @@ VNET_SYSUNINIT(vnet_if_return, SI_SUB_VNET_DONE, SI_ORDER_ANY, vnet_if_return, NULL); #endif -static void * -if_grow(void) -{ - int oldlim; - u_int n; - struct ifnet **e; - void *old; - - old = NULL; - IFNET_WLOCK_ASSERT(); - oldlim = V_if_indexlim; - IFNET_WUNLOCK(); - n = (oldlim << 1) * sizeof(*e); - e = malloc(n, M_IFNET, M_WAITOK | M_ZERO); - IFNET_WLOCK(); - if (V_if_indexlim != oldlim) { - free(e, M_IFNET); - return (NULL); - } - if (V_ifindex_table != NULL) { - memcpy((caddr_t)e, (caddr_t)V_ifindex_table, n/2); - old = V_ifindex_table; - } - V_if_indexlim <<= 1; - V_ifindex_table = e; - return (old); -} - /* * Allocate a struct ifnet and an index for an interface. A layer 2 * common structure will also be allocated if an allocation routine is @@ -586,8 +560,6 @@ static struct ifnet * if_alloc_domain(u_char type, int numa_domain) { struct ifnet *ifp; - u_short idx; - void *old; KASSERT(numa_domain <= IF_NODOM, ("numa_domain too large")); if (numa_domain == IF_NODOM) @@ -627,17 +599,7 @@ if_alloc_domain(u_char type, int numa_domain) ifp->if_get_counter = if_get_counter_default; ifp->if_pcp = IFNET_PCP_NONE; -restart: - IFNET_WLOCK(); - idx = ifindex_alloc(&old); - if (__predict_false(idx == USHRT_MAX)) { - IFNET_WUNLOCK(); - epoch_wait_preempt(net_epoch_preempt); - free(old, M_IFNET); - goto restart; - } - ifnet_setbyindex(idx, ifp); - IFNET_WUNLOCK(); + ifindex_alloc(ifp); return (ifp); } @@ -1301,9 +1263,6 @@ finish_vnet_shutdown: /* * if_vmove() performs a limited version of if_detach() in current * vnet and if_attach()es the ifnet to the vnet specified as 2nd arg. - * An attempt is made to shrink if_index in current vnet, find an - * unused if_index in target vnet and calls if_grow() if necessary, - * and finally find an unused if_xname for the target vnet. */ static int if_vmove(struct ifnet *ifp, struct vnet *new_vnet) @@ -1312,7 +1271,6 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet) #ifdef DEV_BPF u_int bif_dlt, bif_hdrlen; #endif - void *old; int rc; #ifdef DEV_BPF @@ -1355,18 +1313,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet) * Switch to the context of the target vnet. */ CURVNET_SET_QUIET(new_vnet); - restart: - IFNET_WLOCK(); - ifp->if_index = ifindex_alloc(&old); - if (__predict_false(ifp->if_index == USHRT_MAX)) { - IFNET_WUNLOCK(); - epoch_wait_preempt(net_epoch_preempt); - free(old, M_IFNET); - goto restart; - } - ifnet_setbyindex(ifp->if_index, ifp); - IFNET_WUNLOCK(); - + ifindex_alloc(ifp); if_attach_internal(ifp, 1, ifc); #ifdef DEV_BPF