aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2017-06-25 01:41:07 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2017-06-25 01:41:07 +0000
commit64290befc1e7023f3dc0120228a717e521d4c3da (patch)
treedd2cc43ef8b36c38c3c6a1deef69a90f1338bb00 /sys/kern
parent2d44649837d93bcc1e8814a1935125f4437beea6 (diff)
downloadsrc-64290befc1e7023f3dc0120228a717e521d4c3da.tar.gz
src-64290befc1e7023f3dc0120228a717e521d4c3da.zip
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.
Notes
Notes: svn path=/head/; revision=320324
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/uipc_sockbuf.c74
-rw-r--r--sys/kern/uipc_socket.c45
2 files changed, 76 insertions, 43 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 45c69c4b14d4..51874fbbb25b 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -451,14 +451,78 @@ sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so,
}
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);
}
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 55f5cdcd6801..129a0a2842b2 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -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: