tcp: reduce memory footprint when listing tcp hostcache
In tcp_hostcache_list, the sbuf used would need a large (~2MB) blocking allocation of memory (M_WAITOK), when listing a full hostcache. This may stall the requestor for an indeterminate time. A further optimization is to return the expected userspace buffersize right away, rather than preparing the output of each current entry of the hostcase, provided by: @tuexen. This makes use of the ready-made functions of sbuf to work with sysctl, and repeatedly drain the much smaller buffer. PR: 254333 MFC after: 2 weeks Reviewed By: #transport, tuexen Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D29471
This commit is contained in:
parent
98727c6cd1
commit
cb0dd7e122
@ -628,7 +628,7 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
const int linesize = 128;
|
||||
struct sbuf sb;
|
||||
int i, error;
|
||||
int i, error, len;
|
||||
struct hc_metrics *hc_entry;
|
||||
char ip4buf[INET_ADDRSTRLEN];
|
||||
#ifdef INET6
|
||||
@ -638,11 +638,22 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
|
||||
if (jailed_without_vnet(curthread->td_ucred) != 0)
|
||||
return (EPERM);
|
||||
|
||||
sbuf_new(&sb, NULL, linesize * (V_tcp_hostcache.cache_count + 1),
|
||||
SBUF_INCLUDENUL);
|
||||
/* Optimize Buffer length query by sbin/sysctl */
|
||||
if (req->oldptr == NULL) {
|
||||
len = (V_tcp_hostcache.cache_count + 1) * linesize;
|
||||
return (SYSCTL_OUT(req, NULL, len));
|
||||
}
|
||||
|
||||
error = sysctl_wire_old_buffer(req, 0);
|
||||
if (error != 0) {
|
||||
return(error);
|
||||
}
|
||||
|
||||
/* Use a buffer for 16 lines */
|
||||
sbuf_new_for_sysctl(&sb, NULL, 16 * linesize, req);
|
||||
|
||||
sbuf_printf(&sb,
|
||||
"\nIP address MTU SSTRESH RTT RTTVAR "
|
||||
"\nIP address MTU SSTRESH RTT RTTVAR "
|
||||
" CWND SENDPIPE RECVPIPE HITS UPD EXP\n");
|
||||
|
||||
#define msec(u) (((u) + 500) / 1000)
|
||||
@ -677,8 +688,6 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
#undef msec
|
||||
error = sbuf_finish(&sb);
|
||||
if (error == 0)
|
||||
error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
|
||||
sbuf_delete(&sb);
|
||||
return(error);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user