sockbufs: add sbreserve_locked_limit() with custom maxsockbuf limit.

Protocols such as netlink may need a large socket receive buffer,
 measured in tens of megabytes. This change allows netlink to
 set larger socket buffers (given the privs are in place), without
 requiring user to manuall bump maxsockbuf.

Reviewed by:	glebius
Differential Revision: https://reviews.freebsd.org/D36747
This commit is contained in:
Alexander V. Chernikov 2022-09-27 13:52:11 +00:00
parent f66968564d
commit 7b660faa9e
2 changed files with 17 additions and 7 deletions

View File

@ -66,9 +66,10 @@ void (*aio_swake)(struct socket *, struct sockbuf *);
* Primitive routines for operating on socket buffers
*/
#define BUF_MAX_ADJ(_sz) (((u_quad_t)(_sz)) * MCLBYTES / (MSIZE + MCLBYTES))
u_long sb_max = SB_MAX;
u_long sb_max_adj =
(quad_t)SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */
u_long sb_max_adj = BUF_MAX_ADJ(SB_MAX);
static u_long sb_efficiency = 8; /* parameter for sbreserve() */
@ -611,7 +612,7 @@ sysctl_handle_sb_max(SYSCTL_HANDLER_ARGS)
if (tmp_sb_max < MSIZE + MCLBYTES)
return (EINVAL);
sb_max = tmp_sb_max;
sb_max_adj = (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES);
sb_max_adj = BUF_MAX_ADJ(sb_max);
return (0);
}
@ -620,8 +621,8 @@ sysctl_handle_sb_max(SYSCTL_HANDLER_ARGS)
* become limiting if buffering efficiency is near the normal case.
*/
bool
sbreserve_locked(struct socket *so, sb_which which, u_long cc,
struct thread *td)
sbreserve_locked_limit(struct socket *so, sb_which which, u_long cc,
u_long buf_max, struct thread *td)
{
struct sockbuf *sb = sobuf(so, which);
rlim_t sbsize_limit;
@ -635,7 +636,7 @@ sbreserve_locked(struct socket *so, sb_which which, u_long cc,
* appropriate thread resource limits are available. In that case,
* we don't apply a process limit.
*/
if (cc > sb_max_adj)
if (cc > BUF_MAX_ADJ(buf_max))
return (false);
if (td != NULL) {
sbsize_limit = lim_cur(td, RLIMIT_SBSIZE);
@ -644,12 +645,19 @@ sbreserve_locked(struct socket *so, sb_which which, u_long cc,
if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc,
sbsize_limit))
return (false);
sb->sb_mbmax = min(cc * sb_efficiency, sb_max);
sb->sb_mbmax = min(cc * sb_efficiency, buf_max);
if (sb->sb_lowat > sb->sb_hiwat)
sb->sb_lowat = sb->sb_hiwat;
return (true);
}
bool
sbreserve_locked(struct socket *so, sb_which which, u_long cc,
struct thread *td)
{
return (sbreserve_locked_limit(so, which, cc, sb_max, td));
}
int
sbsetopt(struct socket *so, struct sockopt *sopt)
{

View File

@ -231,6 +231,8 @@ void sbrelease_locked(struct socket *, sb_which);
int sbsetopt(struct socket *so, struct sockopt *);
bool sbreserve_locked(struct socket *so, sb_which which, u_long cc,
struct thread *td);
bool sbreserve_locked_limit(struct socket *so, sb_which which, u_long cc,
u_long buf_max, struct thread *td);
void sbsndptr_adv(struct sockbuf *sb, struct mbuf *mb, u_int len);
struct mbuf *
sbsndptr_noadv(struct sockbuf *sb, u_int off, u_int *moff);