Blockdata fixes and tuning.
diff --git a/src/blockdata.c b/src/blockdata.c
index 1da78b7..16a1d94 100644
--- a/src/blockdata.c
+++ b/src/blockdata.c
@@ -18,13 +18,29 @@
#ifdef HAVE_DNSSEC
-static struct blockdata *keyblock_free = NULL;
-static unsigned int blockdata_count = 0, blockdata_hwm = 0;
+static struct blockdata *keyblock_free;
+static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
+
+/* Preallocate some blocks, proportional to cachesize, to reduce heap fragmentation. */
+void blockdata_init(void)
+{
+ int i;
+
+ blockdata_alloced = (daemon->cachesize * 100) / sizeof(struct blockdata);
+
+ keyblock_free = safe_malloc(blockdata_alloced * sizeof(struct blockdata));
+ keyblock_free[blockdata_alloced-1].next = NULL;
+ for (i = 0; i < blockdata_alloced - 1; i++)
+ keyblock_free[i].next = &keyblock_free[i+1];
+
+ blockdata_count = 0;
+ blockdata_hwm = 0;
+}
void blockdata_report(void)
{
- my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u"),
- blockdata_count * sizeof(struct blockdata), blockdata_hwm * sizeof(struct blockdata));
+ my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
+ blockdata_count * sizeof(struct blockdata), blockdata_hwm * sizeof(struct blockdata), blockdata_alloced * sizeof(struct blockdata));
}
struct blockdata *blockdata_alloc(char *data, size_t len)
@@ -44,8 +60,8 @@
else if ((block = whine_malloc(sizeof(struct blockdata))))
{
blockdata_count++;
- if (blockdata_hwm < blockdata_count)
- blockdata_hwm = blockdata_count;
+ if (blockdata_alloced < blockdata_count)
+ blockdata_alloced = blockdata_count;
}
if (!block)
@@ -54,6 +70,9 @@
blockdata_free(ret);
return NULL;
}
+
+ if (blockdata_hwm < blockdata_count)
+ blockdata_hwm = blockdata_count;
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
memcpy(block->key, data, blen);
@@ -70,7 +89,7 @@
void blockdata_free(struct blockdata *blocks)
{
struct blockdata *tmp;
-
+
if (blocks)
{
for (tmp = blocks; tmp->next; tmp = tmp->next)
diff --git a/src/cache.c b/src/cache.c
index 51764eb..3fe137d 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -170,7 +170,22 @@
crecp->hash_next = *up;
*up = crecp;
}
-
+
+#ifdef HAVE_DNSSEC
+static void cache_blockdata_free(struct crec *crecp)
+{
+ if (crecp->flags & F_DNSKEY)
+ {
+ if (crecp->flags & F_DS)
+ blockdata_free(crecp->addr.sig.keydata);
+ else
+ blockdata_free(crecp->addr.key.keydata);
+ }
+ else if (crecp->flags & F_DS)
+ blockdata_free(crecp->addr.ds.keydata);
+}
+#endif
+
static void cache_free(struct crec *crecp)
{
crecp->flags &= ~F_FORWARD;
@@ -197,8 +212,7 @@
}
#ifdef HAVE_DNSSEC
- if (crecp->flags & (F_DNSKEY | F_DS))
- blockdata_free(crecp->addr.key.keydata);
+ cache_blockdata_free(crecp);
#endif
}
@@ -957,8 +971,7 @@
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
{
#ifdef HAVE_DNSSEC
- if (cache->flags & (F_DNSKEY | F_DS))
- blockdata_free(cache->addr.key.keydata);
+ cache_blockdata_free(cache);
#endif
tmp = cache->hash_next;
if (cache->flags & (F_HOSTS | F_CONFIG))
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 03f9449..6c19c05 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -304,7 +304,12 @@
#endif
if (daemon->port != 0)
- cache_init();
+ {
+ cache_init();
+#ifdef HAVE_DNSSEC
+ blockdata_init();
+#endif
+ }
if (option_bool(OPT_DBUS))
#ifdef HAVE_DBUS
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index f8cc969..5317ea3 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1011,6 +1011,7 @@
/* blockdata.c */
#ifdef HAVE_DNSSEC
+void blockdata_init(void);
void blockdata_report(void);
struct blockdata *blockdata_alloc(char *data, size_t len);
void *blockdata_retrieve(struct blockdata *block, size_t len, void *data);