Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Jun 2017 01:41:08 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r320324 - in head/sys: kern sys
Message-ID:  <201706250141.v5P1f80Q032152@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Sun Jun 25 01:41:07 2017
New Revision: 320324
URL: https://svnweb.freebsd.org/changeset/base/320324

Log:
  Provide sbsetopt() that handles socket buffer related socket options.
  It distinguishes between data flow sockets and listening sockets, and
  in case of the latter doesn't change resource limits, since listening
  sockets don't hold any buffers, they only carry values to be inherited
  by their children.

Modified:
  head/sys/kern/uipc_sockbuf.c
  head/sys/kern/uipc_socket.c
  head/sys/sys/sockbuf.h

Modified: head/sys/kern/uipc_sockbuf.c
==============================================================================
--- head/sys/kern/uipc_sockbuf.c	Sat Jun 24 20:09:23 2017	(r320323)
+++ head/sys/kern/uipc_sockbuf.c	Sun Jun 25 01:41:07 2017	(r320324)
@@ -451,14 +451,78 @@ sbreserve_locked(struct sockbuf *sb, u_long cc, struct
 }
 
 int
-sbreserve(struct sockbuf *sb, u_long cc, struct socket *so, 
-    struct thread *td)
+sbsetopt(struct socket *so, int cmd, u_long cc)
 {
+	struct sockbuf *sb;
+	short *flags;
+	u_int *hiwat, *lowat;
 	int error;
 
-	SOCKBUF_LOCK(sb);
-	error = sbreserve_locked(sb, cc, so, td);
-	SOCKBUF_UNLOCK(sb);
+	SOCK_LOCK(so);
+	if (SOLISTENING(so)) {
+		switch (cmd) {
+			case SO_SNDLOWAT:
+			case SO_SNDBUF:
+				lowat = &so->sol_sbsnd_lowat;
+				hiwat = &so->sol_sbsnd_hiwat;
+				flags = &so->sol_sbsnd_flags;
+				break;
+			case SO_RCVLOWAT:
+			case SO_RCVBUF:
+				lowat = &so->sol_sbrcv_lowat;
+				hiwat = &so->sol_sbrcv_hiwat;
+				flags = &so->sol_sbrcv_flags;
+				break;
+		}
+	} else {
+		switch (cmd) {
+			case SO_SNDLOWAT:
+			case SO_SNDBUF:
+				sb = &so->so_snd;
+				break;
+			case SO_RCVLOWAT:
+			case SO_RCVBUF:
+				sb = &so->so_rcv;
+				break;
+		}
+		flags = &sb->sb_flags;
+		hiwat = &sb->sb_hiwat;
+		lowat = &sb->sb_lowat;
+		SOCKBUF_LOCK(sb);
+	}
+
+	error = 0;
+	switch (cmd) {
+	case SO_SNDBUF:
+	case SO_RCVBUF:
+		if (SOLISTENING(so)) {
+			if (cc > sb_max_adj) {
+				error = ENOBUFS;
+				break;
+			}
+			*hiwat = cc;
+			if (*lowat > *hiwat)
+				*lowat = *hiwat;
+		} else {
+			if (!sbreserve_locked(sb, cc, so, curthread))
+				error = ENOBUFS;
+		}
+		if (error == 0)
+			*flags &= ~SB_AUTOSIZE;
+		break;
+	case SO_SNDLOWAT:
+	case SO_RCVLOWAT:
+		/*
+		 * Make sure the low-water is never greater than the
+		 * high-water.
+		 */
+		*lowat = (cc > *hiwat) ? *hiwat : cc;
+		break;
+	}
+
+	if (!SOLISTENING(so))
+		SOCKBUF_UNLOCK(sb);
+	SOCK_UNLOCK(so);
 	return (error);
 }
 

Modified: head/sys/kern/uipc_socket.c
==============================================================================
--- head/sys/kern/uipc_socket.c	Sat Jun 24 20:09:23 2017	(r320323)
+++ head/sys/kern/uipc_socket.c	Sun Jun 25 01:41:07 2017	(r320324)
@@ -461,12 +461,6 @@ sodealloc(struct socket *so)
 	so->so_vnet->vnet_sockcnt--;
 #endif
 	mtx_unlock(&so_global_mtx);
-	if (so->so_rcv.sb_hiwat)
-		(void)chgsbsize(so->so_cred->cr_uidinfo,
-		    &so->so_rcv.sb_hiwat, 0, RLIM_INFINITY);
-	if (so->so_snd.sb_hiwat)
-		(void)chgsbsize(so->so_cred->cr_uidinfo,
-		    &so->so_snd.sb_hiwat, 0, RLIM_INFINITY);
 #ifdef MAC
 	mac_socket_destroy(so);
 #endif
@@ -478,6 +472,12 @@ sodealloc(struct socket *so)
 		if (so->sol_accept_filter != NULL)
 			accept_filt_setopt(so, NULL);
 	} else {
+		if (so->so_rcv.sb_hiwat)
+			(void)chgsbsize(so->so_cred->cr_uidinfo,
+			    &so->so_rcv.sb_hiwat, 0, RLIM_INFINITY);
+		if (so->so_snd.sb_hiwat)
+			(void)chgsbsize(so->so_cred->cr_uidinfo,
+			    &so->so_snd.sb_hiwat, 0, RLIM_INFINITY);
 		sx_destroy(&so->so_snd.sb_sx);
 		sx_destroy(&so->so_rcv.sb_sx);
 		SOCKBUF_LOCK_DESTROY(&so->so_snd);
@@ -2834,38 +2834,7 @@ sosetopt(struct socket *so, struct sockopt *sopt)
 				goto bad;
 			}
 
-			switch (sopt->sopt_name) {
-			case SO_SNDBUF:
-			case SO_RCVBUF:
-				if (sbreserve(sopt->sopt_name == SO_SNDBUF ?
-				    &so->so_snd : &so->so_rcv, (u_long)optval,
-				    so, curthread) == 0) {
-					error = ENOBUFS;
-					goto bad;
-				}
-				(sopt->sopt_name == SO_SNDBUF ? &so->so_snd :
-				    &so->so_rcv)->sb_flags &= ~SB_AUTOSIZE;
-				break;
-
-			/*
-			 * Make sure the low-water is never greater than the
-			 * high-water.
-			 */
-			case SO_SNDLOWAT:
-				SOCKBUF_LOCK(&so->so_snd);
-				so->so_snd.sb_lowat =
-				    (optval > so->so_snd.sb_hiwat) ?
-				    so->so_snd.sb_hiwat : optval;
-				SOCKBUF_UNLOCK(&so->so_snd);
-				break;
-			case SO_RCVLOWAT:
-				SOCKBUF_LOCK(&so->so_rcv);
-				so->so_rcv.sb_lowat =
-				    (optval > so->so_rcv.sb_hiwat) ?
-				    so->so_rcv.sb_hiwat : optval;
-				SOCKBUF_UNLOCK(&so->so_rcv);
-				break;
-			}
+			error = sbsetopt(so, sopt->sopt_name, optval);
 			break;
 
 		case SO_SNDTIMEO:

Modified: head/sys/sys/sockbuf.h
==============================================================================
--- head/sys/sys/sockbuf.h	Sat Jun 24 20:09:23 2017	(r320323)
+++ head/sys/sys/sockbuf.h	Sun Jun 25 01:41:07 2017	(r320324)
@@ -167,8 +167,7 @@ void	sbflush_locked(struct sockbuf *sb);
 void	sbrelease(struct sockbuf *sb, struct socket *so);
 void	sbrelease_internal(struct sockbuf *sb, struct socket *so);
 void	sbrelease_locked(struct sockbuf *sb, struct socket *so);
-int	sbreserve(struct sockbuf *sb, u_long cc, struct socket *so,
-	    struct thread *td);
+int	sbsetopt(struct socket *so, int cmd, u_long cc);
 int	sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so,
 	    struct thread *td);
 struct mbuf *



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706250141.v5P1f80Q032152>