Index: net/if.c =================================================================== --- net/if.c (revision 223932) +++ net/if.c (working copy) @@ -171,6 +171,8 @@ static void if_delgroups(struct ifnet *); static void if_attach_internal(struct ifnet *, int); static void if_detach_internal(struct ifnet *, int); +static int ifnet_ctor(void *, int, void *, int); +static void ifnet_dtor(void *, int, void *); #ifdef INET6 /* @@ -180,6 +182,7 @@ extern void nd6_setmtu(struct ifnet *); #endif +VNET_DEFINE(uma_zone_t, ifnet_zone); VNET_DEFINE(int, if_index); int ifqmaxlen = IFQ_MAXLEN; VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */ @@ -190,6 +193,7 @@ /* Table of ifnet by index. */ VNET_DEFINE(struct ifindex_entry *, ifindex_table); +#define V_ifnet_zone VNET(ifnet_zone) #define V_if_indexlim VNET(if_indexlim) #define V_ifindex_table VNET(ifindex_table) @@ -215,7 +219,7 @@ static if_com_alloc_t *if_com_alloc[256]; static if_com_free_t *if_com_free[256]; -MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals"); +MALLOC_DEFINE(M_IFNET, "ifnet", "interface table"); MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address"); MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); @@ -354,6 +358,8 @@ vnet_if_init(const void *unused __unused) { + V_ifnet_zone = uma_zcreate("ifnet", sizeof(struct ifnet), ifnet_ctor, + ifnet_dtor, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); TAILQ_INIT(&V_ifnet); TAILQ_INIT(&V_ifg_head); IFNET_WLOCK(); @@ -416,35 +422,35 @@ V_ifindex_table = e; } -/* - * Allocate a struct ifnet and an index for an interface. A layer 2 - * common structure will also be allocated if an allocation routine is - * registered for the passed type. - */ -struct ifnet * -if_alloc(u_char type) +static int +ifnet_ctor(void *mem, int size, void *arg, int flags) { - struct ifnet *ifp; + struct ifnet *ifp = (struct ifnet *)mem; + int error; u_short idx; + u_char type; - ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO); IFNET_WLOCK(); - if (ifindex_alloc_locked(&idx) != 0) { + if ((error = ifindex_alloc_locked(&idx)) != 0) { IFNET_WUNLOCK(); - free(ifp, M_IFNET); - return (NULL); + return (error); } ifnet_setbyindex_locked(idx, IFNET_HOLD); IFNET_WUNLOCK(); + + bzero(ifp, sizeof(struct ifnet)); + ifp->if_index = idx; + + type = *(u_char *)arg; + ifp->if_type = type; ifp->if_alloctype = type; if (if_com_alloc[type] != NULL) { ifp->if_l2com = if_com_alloc[type](type, ifp); if (ifp->if_l2com == NULL) { - free(ifp, M_IFNET); ifindex_free(idx); - return (NULL); + return (ENOMEM); } } @@ -463,20 +469,33 @@ refcount_init(&ifp->if_refcount, 1); /* Index reference. */ ifnet_setbyindex(ifp->if_index, ifp); - return (ifp); + + return (0); } /* + * Allocate a struct ifnet and an index for an interface. A layer 2 + * common structure will also be allocated if an allocation routine is + * registered for the passed type. + */ +struct ifnet * +if_alloc(u_char type) +{ + return (struct ifnet *)uma_zalloc_arg(V_ifnet_zone, &type, M_WAITOK); +} + +/* * Do the actual work of freeing a struct ifnet, and layer 2 common * structure. This call is made when the last reference to an * interface is released. */ static void -if_free_internal(struct ifnet *ifp) +ifnet_dtor(void *mem, int size, void *arg) { + struct ifnet *ifp = (struct ifnet *)mem; KASSERT((ifp->if_flags & IFF_DYING), - ("if_free_internal: interface not dying")); + ("ifnet_dtor: interface not dying")); if (if_com_free[ifp->if_alloctype] != NULL) if_com_free[ifp->if_alloctype](ifp->if_l2com, @@ -490,7 +509,6 @@ IF_AFDATA_DESTROY(ifp); IF_ADDR_LOCK_DESTROY(ifp); ifq_delete(&ifp->if_snd); - free(ifp, M_IFNET); } /* @@ -518,7 +536,7 @@ if (!refcount_release(&ifp->if_refcount)) return; - if_free_internal(ifp); + uma_zfree(V_ifnet_zone, ifp); } /* @@ -552,7 +570,7 @@ if (!refcount_release(&ifp->if_refcount)) return; - if_free_internal(ifp); + uma_zfree(V_ifnet_zone, ifp); } void