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);

Reply via email to