From 3f6a7c52ac5055f63b3e2fe6ed434a7716266cb2 Mon Sep 17 00:00:00 2001 From: ozaki-r Date: Wed, 26 Nov 2014 07:43:04 +0000 Subject: [PATCH] Create if_slowtimo (if_watchdog) callout for each interface This change is to obviate the need to run if_slowtimo callbacks that may sleep inside IFNET_FOREACH. And also by this change we can turn on MPSAFE of callouts individually. Discussed with uebayasi@ and riastradh@. --- sys/net/if.c | 39 ++++++++++++++++++++++----------------- sys/net/if.h | 6 +++++- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index d9eba80bcf01..2b83eb3e55ac 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $NetBSD: if.c,v 1.295 2014/11/26 07:22:05 ozaki-r Exp $ */ +/* $NetBSD: if.c,v 1.296 2014/11/26 07:43:04 ozaki-r Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -90,7 +90,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.295 2014/11/26 07:22:05 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.296 2014/11/26 07:43:04 ozaki-r Exp $"); #include "opt_inet.h" @@ -168,8 +168,6 @@ static kmutex_t if_clone_mtx; static struct ifaddr ** ifnet_addrs = NULL; -static callout_t if_slowtimo_ch; - struct ifnet *lo0ifp; int ifqmaxlen = IFQ_MAXLEN; @@ -236,9 +234,6 @@ ifinit(void) sysctl_net_pktq_setup(NULL, PF_INET6); #endif - callout_init(&if_slowtimo_ch, 0); - if_slowtimo(NULL); - if_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, if_listener_cb, NULL); @@ -638,6 +633,12 @@ if_attach(ifnet_t *ifp) /* Announce the interface. */ rt_ifannouncemsg(ifp, IFAN_ARRIVAL); + + if (ifp->if_slowtimo != NULL) { + callout_init(&ifp->if_slowtimo_ch, 0); + callout_setfunc(&ifp->if_slowtimo_ch, if_slowtimo, ifp); + if_slowtimo(ifp); + } } void @@ -737,6 +738,11 @@ if_detach(struct ifnet *ifp) s = splnet(); + if (ifp->if_slowtimo != NULL) { + callout_halt(&ifp->if_slowtimo_ch, NULL); + callout_destroy(&ifp->if_slowtimo_ch); + } + /* * Do an if_down() to give protocols a chance to do something. */ @@ -1494,24 +1500,23 @@ if_up(struct ifnet *ifp) } /* - * Handle interface slowtimo timer routines. Called - * from softclock, we decrement timers (if set) and + * Handle interface slowtimo timer routine. Called + * from softclock, we decrement timer (if set) and * call the appropriate interface routine on expiration. */ static void if_slowtimo(void *arg) { - struct ifnet *ifp; + struct ifnet *ifp = arg; int s = splnet(); - IFNET_FOREACH(ifp) { - if (ifp->if_timer == 0 || --ifp->if_timer) - continue; - if (ifp->if_slowtimo != NULL) - (*ifp->if_slowtimo)(ifp); - } + KASSERT(ifp->if_slowtimo != NULL); + + if (ifp->if_timer != 0 && --ifp->if_timer == 0) + (*ifp->if_slowtimo)(ifp); + splx(s); - callout_reset(&if_slowtimo_ch, hz / IFNET_SLOWHZ, if_slowtimo, NULL); + callout_schedule(&ifp->if_slowtimo_ch, hz / IFNET_SLOWHZ); } /* diff --git a/sys/net/if.h b/sys/net/if.h index f5a889ff3467..50e124a2cf87 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $NetBSD: if.h,v 1.177 2014/11/26 07:22:05 ozaki-r Exp $ */ +/* $NetBSD: if.h,v 1.178 2014/11/26 07:43:04 ozaki-r Exp $ */ /*- * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -214,6 +214,7 @@ struct ifnet_lock; #ifdef _KERNEL #include #include +#include struct ifnet_lock { kmutex_t il_lock; /* Protects the critical section. */ @@ -342,6 +343,9 @@ typedef struct ifnet { const struct sockaddr *); int (*if_setflags)(struct ifnet *, const short); struct ifnet_lock *if_ioctl_lock; +#ifdef _KERNEL /* XXX kvm(3) */ + callout_t if_slowtimo_ch; +#endif } ifnet_t; #define if_mtu if_data.ifi_mtu