git: 7b660faa9e30 - main - sockbufs: add sbreserve_locked_limit() with custom maxsockbuf limit.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 28 Sep 2022 10:20:21 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=7b660faa9e30c15d3be9b2c44c3ca046a33331f4

commit 7b660faa9e30c15d3be9b2c44c3ca046a33331f4
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2022-09-27 13:52:11 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2022-09-28 10:20:09 +0000

    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
---
 sys/kern/uipc_sockbuf.c | 22 +++++++++++++++-------
 sys/sys/sockbuf.h       |  2 ++
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index a2d3fc28bbec..61ec0c794270 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -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)
 {
diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h
index a0c6fd10116a..33c0abb381a3 100644
--- a/sys/sys/sockbuf.h
+++ b/sys/sys/sockbuf.h
@@ -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);