On Mon, Jan 30, 2023 at 05:03:30PM +0300, Vitaliy Makkoveev wrote:
> It makes sense to push solock() down to sosetopt() too. For a half cases
> (*pr_ctloutput)() is just null op, so there is no reason to call it.
> Also, a lot of things could be done without solock() held.
You do a bunch of things together
- push solock()
- move code around
- return error instead of error =
- set sb to &so->so_snd or &so->so_rcv
Some of the refactorings make sense, others change the code just
to be different in my eyes.
Can we discuss theses things in separate diffs?
bluhm
> Index: sys/kern/uipc_socket.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_socket.c,v
> retrieving revision 1.299
> diff -u -p -r1.299 uipc_socket.c
> --- sys/kern/uipc_socket.c 27 Jan 2023 21:01:59 -0000 1.299
> +++ sys/kern/uipc_socket.c 30 Jan 2023 14:02:29 -0000
> @@ -1777,63 +1777,25 @@ sosetopt(struct socket *so, int level, i
> {
> int error = 0;
>
> - soassertlocked(so);
> -
> if (level != SOL_SOCKET) {
> if (so->so_proto->pr_ctloutput) {
> + solock(so);
> error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
> level, optname, m);
> + sounlock(so);
> return (error);
> - }
> - error = ENOPROTOOPT;
> + } else
> + return (ENOPROTOOPT);
> } else {
> switch (optname) {
> - case SO_BINDANY:
> - if ((error = suser(curproc)) != 0) /* XXX */
> - return (error);
> - break;
> - }
> -
> - switch (optname) {
> -
> - case SO_LINGER:
> - if (m == NULL || m->m_len != sizeof (struct linger) ||
> - mtod(m, struct linger *)->l_linger < 0 ||
> - mtod(m, struct linger *)->l_linger > SHRT_MAX)
> - return (EINVAL);
> - so->so_linger = mtod(m, struct linger *)->l_linger;
> - /* FALLTHROUGH */
> -
> - case SO_BINDANY:
> - case SO_DEBUG:
> - case SO_KEEPALIVE:
> - case SO_USELOOPBACK:
> - case SO_BROADCAST:
> - case SO_REUSEADDR:
> - case SO_REUSEPORT:
> - case SO_OOBINLINE:
> - case SO_TIMESTAMP:
> - case SO_ZEROIZE:
> - if (m == NULL || m->m_len < sizeof (int))
> - return (EINVAL);
> - if (*mtod(m, int *))
> - so->so_options |= optname;
> - else
> - so->so_options &= ~optname;
> - break;
> -
> - case SO_DONTROUTE:
> - if (m == NULL || m->m_len < sizeof (int))
> - return (EINVAL);
> - if (*mtod(m, int *))
> - error = EOPNOTSUPP;
> - break;
> -
> case SO_SNDBUF:
> case SO_RCVBUF:
> case SO_SNDLOWAT:
> case SO_RCVLOWAT:
> {
> + struct sockbuf *sb = (
> + optname == (SO_SNDBUF | SO_SNDLOWAT) ?
> + &so->so_snd : &so->so_rcv);
> u_long cnt;
>
> if (m == NULL || m->m_len < sizeof (int))
> @@ -1841,43 +1803,42 @@ sosetopt(struct socket *so, int level, i
> cnt = *mtod(m, int *);
> if ((long)cnt <= 0)
> cnt = 1;
> - switch (optname) {
>
> - case SO_SNDBUF:
> - if (so->so_snd.sb_state & SS_CANTSENDMORE)
> - return (EINVAL);
> - if (sbcheckreserve(cnt, so->so_snd.sb_wat) ||
> - sbreserve(so, &so->so_snd, cnt))
> - return (ENOBUFS);
> - so->so_snd.sb_wat = cnt;
> - break;
> + solock(so);
>
> + switch (optname) {
> + case SO_SNDBUF:
> case SO_RCVBUF:
> - if (so->so_rcv.sb_state & SS_CANTRCVMORE)
> - return (EINVAL);
> - if (sbcheckreserve(cnt, so->so_rcv.sb_wat) ||
> - sbreserve(so, &so->so_rcv, cnt))
> - return (ENOBUFS);
> - so->so_rcv.sb_wat = cnt;
> + if (sb->sb_state &
> + (SS_CANTSENDMORE | SS_CANTRCVMORE)) {
> + error = EINVAL;
> + break;
> + }
> + if (sbcheckreserve(cnt, sb->sb_wat) ||
> + sbreserve(so, sb, cnt)) {
> + error = ENOBUFS;
> + break;
> + }
> + sb->sb_wat = cnt;
> break;
>
> - case SO_SNDLOWAT:
> - so->so_snd.sb_lowat =
> - (cnt > so->so_snd.sb_hiwat) ?
> - so->so_snd.sb_hiwat : cnt;
> - break;
> case SO_RCVLOWAT:
> - so->so_rcv.sb_lowat =
> - (cnt > so->so_rcv.sb_hiwat) ?
> - so->so_rcv.sb_hiwat : cnt;
> + case SO_SNDLOWAT:
> + sb->sb_lowat = (cnt > sb->sb_hiwat) ?
> + sb->sb_hiwat : cnt;
> break;
> }
> - break;
> +
> + sounlock(so);
> +
> + return (error);
> }
>
> case SO_SNDTIMEO:
> case SO_RCVTIMEO:
> {
> + struct sockbuf *sb = (optname == SO_SNDTIMEO ?
> + &so->so_snd : &so->so_rcv);
> struct timeval tv;
> uint64_t nsecs;
>
> @@ -1891,16 +1852,12 @@ sosetopt(struct socket *so, int level, i
> return (EDOM);
> if (nsecs == 0)
> nsecs = INFSLP;
> - switch (optname) {
>
> - case SO_SNDTIMEO:
> - so->so_snd.sb_timeo_nsecs = nsecs;
> - break;
> - case SO_RCVTIMEO:
> - so->so_rcv.sb_timeo_nsecs = nsecs;
> - break;
> - }
> - break;
> + solock(so);
> + sb->sb_timeo_nsecs = nsecs;
> + sounlock(so);
> +
> + return (0);
> }
>
> case SO_RTABLE:
> @@ -1911,18 +1868,30 @@ sosetopt(struct socket *so, int level, i
> so->so_proto->pr_domain;
>
> level = dom->dom_protosw->pr_protocol;
> +
> + solock(so);
> error = (*so->so_proto->pr_ctloutput)
> (PRCO_SETOPT, so, level, optname, m);
> + sounlock(so);
> +
> return (error);
> }
> - error = ENOPROTOOPT;
> - break;
> + return (ENOPROTOOPT);
> +
> + case SO_DONTROUTE:
> + if (m == NULL || m->m_len < sizeof (int))
> + return (EINVAL);
> + if (*mtod(m, int *))
> + return (EOPNOTSUPP);
> + return (0);
>
> #ifdef SOCKET_SPLICE
> case SO_SPLICE:
> + solock(so);
> if (m == NULL) {
> error = sosplice(so, -1, 0, NULL);
> } else if (m->m_len < sizeof(int)) {
> + sounlock(so);
> return (EINVAL);
> } else if (m->m_len < sizeof(struct splice)) {
> error = sosplice(so, *mtod(m, int *), 0, NULL);
> @@ -1932,9 +1901,52 @@ sosetopt(struct socket *so, int level, i
> mtod(m, struct splice *)->sp_max,
> &mtod(m, struct splice *)->sp_idle);
> }
> - break;
> + sounlock(so);
> +
> + return (error);
> #endif /* SOCKET_SPLICE */
>
> + }
> +
> + switch (optname) {
> + case SO_BINDANY:
> + if ((error = suser(curproc)) != 0) /* XXX */
> + return (error);
> + break;
> + }
> +
> + solock(so);
> +
> + switch (optname) {
> + case SO_LINGER:
> + if (m == NULL || m->m_len != sizeof (struct linger) ||
> + mtod(m, struct linger *)->l_linger < 0 ||
> + mtod(m, struct linger *)->l_linger > SHRT_MAX) {
> + error = EINVAL;
> + break;
> + }
> + so->so_linger = mtod(m, struct linger *)->l_linger;
> + /* FALLTHROUGH */
> + case SO_BINDANY:
> + case SO_DEBUG:
> + case SO_KEEPALIVE:
> + case SO_USELOOPBACK:
> + case SO_BROADCAST:
> + case SO_REUSEADDR:
> + case SO_REUSEPORT:
> + case SO_OOBINLINE:
> + case SO_TIMESTAMP:
> + case SO_ZEROIZE:
> + if (m == NULL || m->m_len < sizeof (int)) {
> + error = EINVAL;
> + break;
> + }
> + if (*mtod(m, int *))
> + so->so_options |= optname;
> + else
> + so->so_options &= ~optname;
> + break;
> +
> default:
> error = ENOPROTOOPT;
> break;
> @@ -1943,6 +1955,8 @@ sosetopt(struct socket *so, int level, i
> (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
> level, optname, m);
> }
> +
> + sounlock(so);
> }
>
> return (error);
> Index: sys/kern/uipc_syscalls.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
> retrieving revision 1.211
> diff -u -p -r1.211 uipc_syscalls.c
> --- sys/kern/uipc_syscalls.c 27 Jan 2023 21:01:59 -0000 1.211
> +++ sys/kern/uipc_syscalls.c 30 Jan 2023 14:02:29 -0000
> @@ -1232,9 +1232,7 @@ sys_setsockopt(struct proc *p, void *v,
> m->m_len = SCARG(uap, valsize);
> }
> so = fp->f_data;
> - solock(so);
> error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
> - sounlock(so);
> bad:
> m_freem(m);
> FRELE(fp, p);