Print this page
Warning about DCE lifetimes
coyright fix
gdamore's feedback
7185 IP DCEs leak from halted non-global zones
*** 20,29 ****
--- 20,30 ----
*/
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2017, OmniTI Computer Consulting, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/strsun.h>
*** 88,97 ****
--- 89,102 ----
* return failure;
* }
*
* Note that for IPv6 link-local addresses we record the ifindex since the
* link-locals are not globally unique.
+ *
+ * DCEs can remain for an arbitrarily long time, until memory pressure or
+ * too-deep hash buckets (see dce_lookup_and_add*()) enable the reclaim thread
+ * to actually remove DCEs from the cache.
*/
/*
* Hash bucket structure for DCEs
*/
*** 324,339 ****
--- 329,369 ----
rw_init(&ipst->ips_dce_hash_v6[i].dcb_lock, NULL, RW_DEFAULT,
NULL);
}
}
+ /*
+ * Given a DCE hash bucket, unlink DCE entries from it. Some callers need
+ * ifindex-specific matching, others don't. Don't overload ifindex to indicate
+ * specificity, just indicate so explicitly.
+ */
+ static void
+ dce_bucket_clean(dcb_t *dcb, boolean_t specific_ifindex, uint_t ifindex)
+ {
+ dce_t *dce, *nextdce;
+
+ rw_enter(&dcb->dcb_lock, RW_WRITER);
+
+ for (dce = dcb->dcb_dce; dce != NULL; dce = nextdce) {
+ nextdce = dce->dce_next;
+ if ((!specific_ifindex) || dce->dce_ifindex == ifindex) {
+ dce_delete_locked(dcb, dce);
+ dce_refrele(dce);
+ }
+ }
+
+ rw_exit(&dcb->dcb_lock);
+ }
+
void
dce_stack_destroy(ip_stack_t *ipst)
{
int i;
for (i = 0; i < ipst->ips_dce_hashsize; i++) {
+ dce_bucket_clean(&ipst->ips_dce_hash_v4[i], B_FALSE, 0);
rw_destroy(&ipst->ips_dce_hash_v4[i].dcb_lock);
+ dce_bucket_clean(&ipst->ips_dce_hash_v6[i], B_FALSE, 0);
rw_destroy(&ipst->ips_dce_hash_v6[i].dcb_lock);
}
kmem_free(ipst->ips_dce_hash_v4,
ipst->ips_dce_hashsize * sizeof (dcb_t));
ipst->ips_dce_hash_v4 = NULL;
*** 953,974 ****
*/
void
dce_cleanup(uint_t ifindex, ip_stack_t *ipst)
{
uint_t i;
- dcb_t *dcb;
- dce_t *dce, *nextdce;
! for (i = 0; i < ipst->ips_dce_hashsize; i++) {
! dcb = &ipst->ips_dce_hash_v6[i];
! rw_enter(&dcb->dcb_lock, RW_WRITER);
!
! for (dce = dcb->dcb_dce; dce != NULL; dce = nextdce) {
! nextdce = dce->dce_next;
! if (dce->dce_ifindex == ifindex) {
! dce_delete_locked(dcb, dce);
! dce_refrele(dce);
! }
! }
! rw_exit(&dcb->dcb_lock);
! }
}
--- 983,991 ----
*/
void
dce_cleanup(uint_t ifindex, ip_stack_t *ipst)
{
uint_t i;
! for (i = 0; i < ipst->ips_dce_hashsize; i++)
! dce_bucket_clean(&ipst->ips_dce_hash_v6[i], B_TRUE, ifindex);
}