On Wed, Aug 02, 2017 at 11:03:13AM +0200, Martin Pieuchot wrote:
> Diff below moves the socket lock "above" sosetopt(), sogetopt() and
> sosplice().  While this adds a lot of lock/unlock dances in NFS, they
> will be merge in a later diff.
> 
> sosetopt() modifies a socket fields so it needs the lock.  sogetopt()
> do not always need it, but it makes the code simpler to always grab
> it and the code section is really small anyway.
> 
> ok?

OK bluhm@

> Index: kern/uipc_socket.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_socket.c,v
> retrieving revision 1.198
> diff -u -p -r1.198 uipc_socket.c
> --- kern/uipc_socket.c        27 Jul 2017 12:05:36 -0000      1.198
> +++ kern/uipc_socket.c        2 Aug 2017 08:21:45 -0000
> @@ -1073,7 +1073,9 @@ sosplice(struct socket *so, int fd, off_
>       struct file     *fp;
>       struct socket   *sosp;
>       struct sosplice *sp;
> -     int              s, error = 0;
> +     int              error = 0;
> +
> +     soassertlocked(so);
>  
>       if (sosplice_taskq == NULL)
>               sosplice_taskq = taskq_create("sosplice", 1, IPL_SOFTNET, 0);
> @@ -1097,17 +1099,14 @@ sosplice(struct socket *so, int fd, off_
>  
>       /* If no fd is given, unsplice by removing existing link. */
>       if (fd < 0) {
> -             s = solock(so);
>               /* Lock receive buffer. */
>               if ((error = sblock(so, &so->so_rcv,
>                   (so->so_state & SS_NBIO) ? M_NOWAIT : M_WAITOK)) != 0) {
> -                     sounlock(s);
>                       return (error);
>               }
>               if (so->so_sp->ssp_socket)
>                       sounsplice(so, so->so_sp->ssp_socket, 1);
>               sbunlock(&so->so_rcv);
> -             sounlock(s);
>               return (0);
>       }
>  
> @@ -1129,17 +1128,14 @@ sosplice(struct socket *so, int fd, off_
>                       pool_put(&sosplice_pool, sp);
>       }
>  
> -     s = solock(so);
>       /* Lock both receive and send buffer. */
>       if ((error = sblock(so, &so->so_rcv,
>           (so->so_state & SS_NBIO) ? M_NOWAIT : M_WAITOK)) != 0) {
> -             sounlock(s);
>               FRELE(fp, curproc);
>               return (error);
>       }
>       if ((error = sblock(so, &sosp->so_snd, M_WAITOK)) != 0) {
>               sbunlock(&so->so_rcv);
> -             sounlock(s);
>               FRELE(fp, curproc);
>               return (error);
>       }
> @@ -1185,7 +1181,6 @@ sosplice(struct socket *so, int fd, off_
>   release:
>       sbunlock(&sosp->so_snd);
>       sbunlock(&so->so_rcv);
> -     sounlock(s);
>       FRELE(fp, curproc);
>       return (error);
>  }
> @@ -1565,15 +1560,15 @@ sowwakeup(struct socket *so)
>  int
>  sosetopt(struct socket *so, int level, int optname, struct mbuf *m0)
>  {
> -     int s, error = 0;
> +     int error = 0;
>       struct mbuf *m = m0;
>  
> +     soassertlocked(so);
> +
>       if (level != SOL_SOCKET) {
>               if (so->so_proto && so->so_proto->pr_ctloutput) {
> -                     s = solock(so);
>                       error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
>                           level, optname, m0);
> -                     sounlock(s);
>                       return (error);
>               }
>               error = ENOPROTOOPT;
> @@ -1647,14 +1642,11 @@ sosetopt(struct socket *so, int level, i
>                                       error = EINVAL;
>                                       goto bad;
>                               }
> -                             s = solock(so);
>                               if (sbcheckreserve(cnt, so->so_snd.sb_wat) ||
>                                   sbreserve(so, &so->so_snd, cnt)) {
> -                                     sounlock(s);
>                                       error = ENOBUFS;
>                                       goto bad;
>                               }
> -                             sounlock(s);
>                               so->so_snd.sb_wat = cnt;
>                               break;
>  
> @@ -1663,14 +1655,11 @@ sosetopt(struct socket *so, int level, i
>                                       error = EINVAL;
>                                       goto bad;
>                               }
> -                             s = solock(so);
>                               if (sbcheckreserve(cnt, so->so_rcv.sb_wat) ||
>                                   sbreserve(so, &so->so_rcv, cnt)) {
> -                                     sounlock(s);
>                                       error = ENOBUFS;
>                                       goto bad;
>                               }
> -                             sounlock(s);
>                               so->so_rcv.sb_wat = cnt;
>                               break;
>  
> @@ -1724,10 +1713,8 @@ sosetopt(struct socket *so, int level, i
>                               struct domain *dom = so->so_proto->pr_domain;
>  
>                               level = dom->dom_protosw->pr_protocol;
> -                             s = solock(so);
>                               error = (*so->so_proto->pr_ctloutput)
>                                   (PRCO_SETOPT, so, level, optname, m0);
> -                             sounlock(s);
>                               return (error);
>                       }
>                       error = ENOPROTOOPT;
> @@ -1756,10 +1743,8 @@ sosetopt(struct socket *so, int level, i
>                       break;
>               }
>               if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
> -                     s = solock(so);
>                       (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
>                           level, optname, m0);
> -                     sounlock(s);
>                       m = NULL;       /* freed by protocol */
>               }
>       }
> @@ -1772,18 +1757,18 @@ bad:
>  int
>  sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)
>  {
> -     int s, error = 0;
> +     int error = 0;
>       struct mbuf *m;
>  
> +     soassertlocked(so);
> +
>       if (level != SOL_SOCKET) {
>               if (so->so_proto && so->so_proto->pr_ctloutput) {
>                       m = m_get(M_WAIT, MT_SOOPTS);
>                       m->m_len = 0;
>  
> -                     s = solock(so);
>                       error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so,
>                           level, optname, m);
> -                     sounlock(s);
>                       if (error) {
>                               m_free(m);
>                               return (error);
> @@ -1869,10 +1854,8 @@ sogetopt(struct socket *so, int level, i
>                               struct domain *dom = so->so_proto->pr_domain;
>  
>                               level = dom->dom_protosw->pr_protocol;
> -                             s = solock(so);
>                               error = (*so->so_proto->pr_ctloutput)
>                                   (PRCO_GETOPT, so, level, optname, m);
> -                             sounlock(s);
>                               if (error) {
>                                       (void)m_free(m);
>                                       return (error);
> @@ -1886,13 +1869,10 @@ sogetopt(struct socket *so, int level, i
>               case SO_SPLICE:
>                   {
>                       off_t len;
> -                     int s;
>  
> -                     s = solock(so);
>                       m->m_len = sizeof(off_t);
>                       len = so->so_sp ? so->so_sp->ssp_len : 0;
>                       memcpy(mtod(m, off_t *), &len, sizeof(off_t));
> -                     sounlock(s);
>                       break;
>                   }
>  #endif /* SOCKET_SPLICE */
> Index: kern/uipc_syscalls.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
> retrieving revision 1.156
> diff -u -p -r1.156 uipc_syscalls.c
> --- kern/uipc_syscalls.c      24 Jul 2017 15:07:39 -0000      1.156
> +++ kern/uipc_syscalls.c      2 Aug 2017 08:17:41 -0000
> @@ -940,7 +940,8 @@ sys_setsockopt(struct proc *p, void *v, 
>       } */ *uap = v;
>       struct file *fp;
>       struct mbuf *m = NULL;
> -     int error;
> +     struct socket *so;
> +     int s, error;
>  
>  
>       if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
> @@ -972,7 +973,10 @@ sys_setsockopt(struct proc *p, void *v, 
>               }
>               m->m_len = SCARG(uap, valsize);
>       }
> -     error = sosetopt(fp->f_data, SCARG(uap, level), SCARG(uap, name), m);
> +     so = fp->f_data;
> +     s = solock(so);
> +     error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
> +     sounlock(s);
>       m = NULL;
>  bad:
>       m_freem(m);
> @@ -993,7 +997,8 @@ sys_getsockopt(struct proc *p, void *v, 
>       struct file *fp;
>       struct mbuf *m = NULL;
>       socklen_t valsize;
> -     int error;
> +     struct socket *so;
> +     int s, error;
>  
>       if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
>               return (error);
> @@ -1007,9 +1012,11 @@ sys_getsockopt(struct proc *p, void *v, 
>                       goto out;
>       } else
>               valsize = 0;
> -     if ((error = sogetopt(fp->f_data, SCARG(uap, level),
> -         SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
> -         m != NULL) {
> +     so = fp->f_data;
> +     s = solock(so);
> +     error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), &m);
> +     sounlock(s);
> +     if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
>               if (valsize > m->m_len)
>                       valsize = m->m_len;
>               error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
> Index: nfs/krpc_subr.c
> ===================================================================
> RCS file: /cvs/src/sys/nfs/krpc_subr.c,v
> retrieving revision 1.29
> diff -u -p -r1.29 krpc_subr.c
> --- nfs/krpc_subr.c   24 Aug 2015 14:00:29 -0000      1.29
> +++ nfs/krpc_subr.c   2 Aug 2017 08:17:41 -0000
> @@ -211,7 +211,7 @@ krpc_call(struct sockaddr_in *sa, u_int 
>       struct rpc_call *call;
>       struct rpc_reply *reply;
>       struct uio auio;
> -     int error, rcvflg, timo, secs, len;
> +     int s, error, rcvflg, timo, secs, len;
>       static u_int32_t xid = 0;
>       char addr[INET_ADDRSTRLEN];
>       int *ip;
> @@ -239,7 +239,10 @@ krpc_call(struct sockaddr_in *sa, u_int 
>       tv.tv_usec = 0;
>       memcpy(mtod(m, struct timeval *), &tv, sizeof tv);
>       m->m_len = sizeof(tv);
> -     if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m)))
> +     s = solock(so);
> +     error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m);
> +     sounlock(s);
> +     if (error)
>               goto out;
>  
>       /*
> @@ -251,7 +254,10 @@ krpc_call(struct sockaddr_in *sa, u_int 
>               on = mtod(m, int32_t *);
>               m->m_len = sizeof(*on);
>               *on = 1;
> -             if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m)))
> +             s = solock(so);
> +             error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m);
> +             sounlock(s);
> +             if (error)
>                       goto out;
>       }
>  
> @@ -264,7 +270,9 @@ krpc_call(struct sockaddr_in *sa, u_int 
>       mopt->m_len = sizeof(int);
>       ip = mtod(mopt, int *);
>       *ip = IP_PORTRANGE_LOW;
> +     s = solock(so);
>       error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
> +     sounlock(s);
>       if (error)
>               goto out;
>  
> @@ -286,7 +294,9 @@ krpc_call(struct sockaddr_in *sa, u_int 
>       mopt->m_len = sizeof(int);
>       ip = mtod(mopt, int *);
>       *ip = IP_PORTRANGE_DEFAULT;
> +     s = solock(so);
>       error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
> +     sounlock(s);
>       if (error)
>               goto out;
>  
> Index: nfs/nfs_socket.c
> ===================================================================
> RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
> retrieving revision 1.120
> diff -u -p -r1.120 nfs_socket.c
> --- nfs/nfs_socket.c  24 Jul 2017 15:07:39 -0000      1.120
> +++ nfs/nfs_socket.c  2 Aug 2017 08:17:41 -0000
> @@ -262,7 +262,9 @@ nfs_connect(struct nfsmount *nmp, struct
>               mopt->m_len = sizeof(int);
>               ip = mtod(mopt, int *);
>               *ip = IP_PORTRANGE_LOW;
> +             s = solock(so);
>               error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
> +             sounlock(s);
>               if (error)
>                       goto bad;
>  
> @@ -282,7 +284,9 @@ nfs_connect(struct nfsmount *nmp, struct
>               mopt->m_len = sizeof(int);
>               ip = mtod(mopt, int *);
>               *ip = IP_PORTRANGE_DEFAULT;
> +             s = solock(so);
>               error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
> +             sounlock(s);
>               if (error)
>                       goto bad;
>       }
> @@ -331,6 +335,7 @@ nfs_connect(struct nfsmount *nmp, struct
>        * Always set receive timeout to detect server crash and reconnect.
>        * Otherwise, we can get stuck in soreceive forever.
>        */
> +     s = solock(so);
>       so->so_rcv.sb_timeo = (5 * hz);
>       if (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_INT))
>               so->so_snd.sb_timeo = (5 * hz);
> @@ -364,7 +369,6 @@ nfs_connect(struct nfsmount *nmp, struct
>               rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR +
>                   sizeof (u_int32_t)) * 2;
>       }
> -     s = solock(so);
>       error = soreserve(so, sndreserve, rcvreserve);
>       sounlock(s);
>       if (error)
> Index: nfs/nfs_syscalls.c
> ===================================================================
> RCS file: /cvs/src/sys/nfs/nfs_syscalls.c,v
> retrieving revision 1.109
> diff -u -p -r1.109 nfs_syscalls.c
> --- nfs/nfs_syscalls.c        27 Jun 2017 12:02:43 -0000      1.109
> +++ nfs/nfs_syscalls.c        2 Aug 2017 08:17:41 -0000
> @@ -249,8 +249,8 @@ nfssvc_addsock(struct file *fp, struct m
>               siz = NFS_MAXPACKET;
>       s = solock(so);
>       error = soreserve(so, siz, siz); 
> -     sounlock(s);
>       if (error) {
> +             sounlock(s);
>               m_freem(mynam);
>               return (error);
>       }
> @@ -277,11 +277,11 @@ nfssvc_addsock(struct file *fp, struct m
>       so->so_rcv.sb_timeo = 0;
>       so->so_snd.sb_flags &= ~SB_NOINTR;
>       so->so_snd.sb_timeo = 0;
> +     sounlock(s);
>       if (tslp)
>               slp = tslp;
>       else {
> -             slp = malloc(sizeof(*slp), M_NFSSVC,
> -                 M_WAITOK|M_ZERO);
> +             slp = malloc(sizeof(*slp), M_NFSSVC, M_WAITOK|M_ZERO);
>               TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
>       }
>       slp->ns_so = so;

Reply via email to