diff --git a/CHANGES b/CHANGES index 47104d87e5..fe143c5fd1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +6188. [performance] Reduce memory consumption by allocating properly + sized send buffers for stream-based transports. + [GL #4038] + 6185. [func] Add "ClientQuota" statistics channel counter, which indicates the number of the resolver's spilled queries due to reaching the clients per query quota. [GL !7978] diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index adec5ced27..b4f461b3e0 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -48,6 +48,10 @@ Bug Fixes a delegation from cache was returned to the client. This has now been fixed. :gl:`#3950` +- BIND could allocate too big buffers when sending data via + stream-based DNS transports, leading to increased memory usage. + This has been fixed. :gl:`#4038` + Known Issues ~~~~~~~~~~~~ diff --git a/lib/ns/client.c b/lib/ns/client.c index 368a9fd77f..5196a74892 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -348,6 +348,7 @@ client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer, INSIST(client->tcpbuf == NULL); client->tcpbuf = isc_mem_get(client->mctx, NS_CLIENT_TCP_BUFFER_SIZE); + client->tcpbuf_size = NS_CLIENT_TCP_BUFFER_SIZE; data = client->tcpbuf; isc_buffer_init(buffer, data, NS_CLIENT_TCP_BUFFER_SIZE); } else { @@ -380,7 +381,17 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) { REQUIRE(client->sendhandle == NULL); - isc_buffer_usedregion(buffer, &r); + if (isc_buffer_base(buffer) == client->tcpbuf) { + size_t used = isc_buffer_usedlength(buffer); + client->tcpbuf = isc_mem_reget(client->manager->mctx, + client->tcpbuf, + client->tcpbuf_size, used); + client->tcpbuf_size = used; + r.base = client->tcpbuf; + r.length = used; + } else { + isc_buffer_usedregion(buffer, &r); + } isc_nmhandle_attach(client->handle, &client->sendhandle); if (isc_nm_is_http_handle(client->handle)) { @@ -450,9 +461,7 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) { return; done: if (client->tcpbuf != NULL) { - isc_mem_put(client->mctx, client->tcpbuf, - NS_CLIENT_TCP_BUFFER_SIZE); - client->tcpbuf = NULL; + isc_mem_put(client->mctx, client->tcpbuf, client->tcpbuf_size); } ns_client_drop(client, result); @@ -736,9 +745,7 @@ renderend: cleanup: if (client->tcpbuf != NULL) { - isc_mem_put(client->mctx, client->tcpbuf, - NS_CLIENT_TCP_BUFFER_SIZE); - client->tcpbuf = NULL; + isc_mem_put(client->mctx, client->tcpbuf, client->tcpbuf_size); } if (cleanup_cctx) { @@ -1620,8 +1627,7 @@ ns__client_reset_cb(void *client0) { ns_client_endrequest(client); if (client->tcpbuf != NULL) { - isc_mem_put(client->mctx, client->tcpbuf, - NS_CLIENT_TCP_BUFFER_SIZE); + isc_mem_put(client->mctx, client->tcpbuf, client->tcpbuf_size); } if (client->keytag != NULL) { diff --git a/lib/ns/include/ns/client.h b/lib/ns/include/ns/client.h index f9d694fdd1..6bd41d4e41 100644 --- a/lib/ns/include/ns/client.h +++ b/lib/ns/include/ns/client.h @@ -184,6 +184,7 @@ struct ns_client { isc_nmhandle_t *prefetchhandle; /* Waiting for prefetch / rpzfetch */ isc_nmhandle_t *updatehandle; /* Waiting for update callback */ unsigned char *tcpbuf; + size_t tcpbuf_size; dns_message_t *message; unsigned char *sendbuf; dns_rdataset_t *opt;