aboutsummaryrefslogtreecommitdiff
path: root/sys/nfsclient/bootp_subr.c
diff options
context:
space:
mode:
authorBill Fumerola <billf@FreeBSD.org>2003-08-07 21:27:17 +0000
committerBill Fumerola <billf@FreeBSD.org>2003-08-07 21:27:17 +0000
commit2766bd022fb9875992a8eaffed726b2f83d792a4 (patch)
treed917f118ba431ce6d25a65bca0a73461c92ade44 /sys/nfsclient/bootp_subr.c
parent4bab0ee5284a5520232764afef461329243dde21 (diff)
downloadsrc-2766bd022fb9875992a8eaffed726b2f83d792a4.tar.gz
src-2766bd022fb9875992a8eaffed726b2f83d792a4.zip
0) preallocate per-interface context structures without the ifnet lock held
1) avoid immediately calling bzero() after malloc() by passing M_ZERO 2) do not initialize individual members of the global context to zero 3) remove an unused assignment of ifctx in bootpc_init() Reviewed by: tegge
Notes
Notes: svn path=/head/; revision=118639
Diffstat (limited to 'sys/nfsclient/bootp_subr.c')
-rw-r--r--sys/nfsclient/bootp_subr.c63
1 files changed, 38 insertions, 25 deletions
diff --git a/sys/nfsclient/bootp_subr.c b/sys/nfsclient/bootp_subr.c
index ee1e824c14b0..61c02c0246e6 100644
--- a/sys/nfsclient/bootp_subr.c
+++ b/sys/nfsclient/bootp_subr.c
@@ -232,7 +232,7 @@ static int xdr_int_decode(struct mbuf **ptr, int *iptr);
static void print_in_addr(struct in_addr addr);
static void print_sin_addr(struct sockaddr_in *addr);
static void clear_sinaddr(struct sockaddr_in *sin);
-static struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx);
+static void allocifctx(struct bootpc_globalcontext *gctx);
static void bootpc_compose_query(struct bootpc_ifcontext *ifctx,
struct bootpc_globalcontext *gctx, struct thread *td);
static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx,
@@ -428,16 +428,15 @@ clear_sinaddr(struct sockaddr_in *sin)
sin->sin_port = 0;
}
-static struct bootpc_ifcontext *
+static void
allocifctx(struct bootpc_globalcontext *gctx)
{
struct bootpc_ifcontext *ifctx;
ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx),
- M_TEMP, M_WAITOK);
+ M_TEMP, M_WAITOK | M_ZERO);
if (ifctx == NULL)
panic("Failed to allocate bootp interface context structure");
- bzero(ifctx, sizeof(*ifctx));
ifctx->xid = gctx->xid;
#ifdef BOOTP_NO_DHCP
ifctx->state = IF_BOOTP_UNRESOLVED;
@@ -445,7 +444,11 @@ allocifctx(struct bootpc_globalcontext *gctx)
ifctx->state = IF_DHCP_UNRESOLVED;
#endif
gctx->xid += 0x100;
- return ifctx;
+ if (gctx->interfaces != NULL)
+ gctx->lastinterface->next = ifctx;
+ else
+ gctx->interfaces = ifctx;
+ gctx->lastinterface = ifctx;
}
static __inline int
@@ -1659,6 +1662,9 @@ bootpc_init(void)
struct bootpc_globalcontext *gctx; /* Global BOOTP context */
struct ifnet *ifp;
int error;
+#ifndef BOOTP_WIRED_TO
+ int ifcnt;
+#endif
struct nfsv3_diskless *nd;
struct thread *td;
@@ -1671,28 +1677,46 @@ bootpc_init(void)
if (nfs_diskless_valid != 0)
return;
- gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK);
+ gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO);
if (gctx == NULL)
panic("Failed to allocate bootp global context structure");
- bzero(gctx, sizeof(*gctx));
gctx->xid = ~0xFFFF;
gctx->starttime = time_second;
- ifctx = allocifctx(gctx);
-
/*
* Find a network interface.
*/
#ifdef BOOTP_WIRED_TO
printf("bootpc_init: wired to interface '%s'\n",
__XSTRING(BOOTP_WIRED_TO));
-#endif
- bzero(&ifctx->ireq, sizeof(ifctx->ireq));
+ allocifctx(gctx);
+#else
+ /*
+ * Preallocate interface context storage, if another interface
+ * attaches and wins the race, it won't be eligible for bootp.
+ */
IFNET_RLOCK();
- for (ifp = TAILQ_FIRST(&ifnet);
+ for (ifp = TAILQ_FIRST(&ifnet), ifcnt = 0;
ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_link)) {
+ if ((ifp->if_flags &
+ (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
+ IFF_BROADCAST)
+ continue;
+ ifcnt++;
+ }
+ IFNET_RUNLOCK();
+ if (ifcnt == 0)
+ panic("bootpc_init: no eligible interfaces");
+ for (; ifcnt > 0; ifcnt--)
+ allocifctx(gctx);
+#endif
+
+ IFNET_RLOCK();
+ for (ifp = TAILQ_FIRST(&ifnet), ifctx = gctx->interfaces;
+ ifp != NULL && ifctx != NULL;
+ ifp = TAILQ_NEXT(ifp, if_link)) {
snprintf(ifctx->ireq.ifr_name, sizeof(ifctx->ireq.ifr_name),
"%s%d", ifp->if_name, ifp->if_unit);
#ifdef BOOTP_WIRED_TO
@@ -1705,18 +1729,12 @@ bootpc_init(void)
IFF_BROADCAST)
continue;
#endif
- if (gctx->interfaces != NULL)
- gctx->lastinterface->next = ifctx;
- else
- gctx->interfaces = ifctx;
ifctx->ifp = ifp;
- gctx->lastinterface = ifctx;
- ifctx = allocifctx(gctx);
+ ifctx = ifctx->next;
}
IFNET_RUNLOCK();
- free(ifctx, M_TEMP);
- if (gctx->interfaces == NULL) {
+ if (gctx->interfaces == NULL || gctx->interfaces->ifp == NULL) {
#ifdef BOOTP_WIRED_TO
panic("bootpc_init: Could not find interface specified "
"by BOOTP_WIRED_TO: "
@@ -1726,17 +1744,12 @@ bootpc_init(void)
#endif
}
- gctx->gotrootpath = 0;
- gctx->gotswappath = 0;
- gctx->gotgw = 0;
-
for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
bootpc_fakeup_interface(ifctx, gctx, td);
for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
bootpc_compose_query(ifctx, gctx, td);
- ifctx = gctx->interfaces;
error = bootpc_call(gctx, td);
if (error != 0) {