Re: solock() & nfs_connect

2017-09-04 Thread Alexander Bluhm
On Fri, Sep 01, 2017 at 06:29:33PM +0200, Martin Pieuchot wrote:
> Here's an alternative approach that pre-allocate mbufs.  This reduce
> the number of MGET() in the function an allow us to do a single
> solock()/sounlock() dance.

Yes, I like that.  You could rename m to nam to be consistent with
other functions and make clear what this mbuf is used for.

> ok?

OK bluhm@

> Index: nfs//nfs_socket.c
> ===
> RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
> retrieving revision 1.126
> diff -u -p -r1.126 nfs_socket.c
> --- nfs//nfs_socket.c 1 Sep 2017 15:05:31 -   1.126
> +++ nfs//nfs_socket.c 1 Sep 2017 16:09:16 -
> @@ -238,20 +238,28 @@ nfs_connect(struct nfsmount *nmp, struct
>   int s, error, rcvreserve, sndreserve;
>   struct sockaddr *saddr;
>   struct sockaddr_in *sin;
> - struct mbuf *m;
> + struct mbuf *m = NULL, *mopt = NULL;
>  
> - if (!(nmp->nm_sotype == SOCK_DGRAM || nmp->nm_sotype == SOCK_STREAM)) {
> - error = EINVAL;
> - goto bad;
> - }
> + if (!(nmp->nm_sotype == SOCK_DGRAM || nmp->nm_sotype == SOCK_STREAM))
> + return (EINVAL);
>  
>   nmp->nm_so = NULL;
>   saddr = mtod(nmp->nm_nam, struct sockaddr *);
>   error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, 
>   nmp->nm_soproto);
> - if (error)
> - goto bad;
> + if (error) {
> + nfs_disconnect(nmp);
> + return (error);
> + }
> +
> + /* Allocate mbufs possibly waiting before grabbing the socket lock. */
> + if (nmp->nm_sotype == SOCK_STREAM || saddr->sa_family == AF_INET)
> + MGET(mopt, M_WAIT, MT_SOOPTS);
> + if (saddr->sa_family == AF_INET)
> + MGET(m, M_WAIT, MT_SONAME);
> +
>   so = nmp->nm_so;
> + s = solock(so);
>   nmp->nm_soflags = so->so_proto->pr_flags;
>  
>   /*
> @@ -260,42 +268,29 @@ nfs_connect(struct nfsmount *nmp, struct
>* disclosure through UDP port capture.
>*/
>   if (saddr->sa_family == AF_INET) {
> - struct mbuf *mopt;
>   int *ip;
>  
> - MGET(mopt, M_WAIT, MT_SOOPTS);
>   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);
> - m_freem(mopt);
>   if (error)
>   goto bad;
>  
> - MGET(m, M_WAIT, MT_SONAME);
>   sin = mtod(m, struct sockaddr_in *);
>   memset(sin, 0, sizeof(*sin));
>   sin->sin_len = m->m_len = sizeof(struct sockaddr_in);
>   sin->sin_family = AF_INET;
>   sin->sin_addr.s_addr = INADDR_ANY;
>   sin->sin_port = htons(0);
> - s = solock(so);
>   error = sobind(so, m, &proc0);
> - sounlock(s);
> - m_freem(m);
>   if (error)
>   goto bad;
>  
> - MGET(mopt, M_WAIT, MT_SOOPTS);
>   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);
> - m_freem(mopt);
>   if (error)
>   goto bad;
>   }
> @@ -310,12 +305,9 @@ nfs_connect(struct nfsmount *nmp, struct
>   goto bad;
>   }
>   } else {
> - s = solock(so);
>   error = soconnect(so, nmp->nm_nam);
> - if (error) {
> - sounlock(s);
> + if (error)
>   goto bad;
> - }
>  
>   /*
>* Wait for the connection to complete. Cribbed from the
> @@ -328,23 +320,19 @@ nfs_connect(struct nfsmount *nmp, struct
>   so->so_error == 0 && rep &&
>   (error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){
>   so->so_state &= ~SS_ISCONNECTING;
> - sounlock(s);
>   goto bad;
>   }
>   }
>   if (so->so_error) {
>   error = so->so_error;
>   so->so_error = 0;
> - sounlock(s);
>   goto bad;
>   }
> - sounlock(s);
>   }
>   /*
>* 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);
> @@ -356,18 +344,14 @@ nfs_connect(s

Re: solock() & nfs_connect

2017-09-01 Thread Martin Pieuchot
On 11/08/17(Fri) 15:32, Martin Pieuchot wrote:
> On 11/08/17(Fri) 20:31, Alexander Bluhm wrote:
> > On Fri, Aug 11, 2017 at 01:18:48PM -0400, Martin Pieuchot wrote:
> > > Diff below merge all solock()/sounlock() dances inside nfs_connect().
> > 
> > Now we sleep for memory while holding the lock.  Is this a good
> > idea?

Here's an alternative approach that pre-allocate mbufs.  This reduce
the number of MGET() in the function an allow us to do a single
solock()/sounlock() dance.

ok?

Index: nfs//nfs_socket.c
===
RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
retrieving revision 1.126
diff -u -p -r1.126 nfs_socket.c
--- nfs//nfs_socket.c   1 Sep 2017 15:05:31 -   1.126
+++ nfs//nfs_socket.c   1 Sep 2017 16:09:16 -
@@ -238,20 +238,28 @@ nfs_connect(struct nfsmount *nmp, struct
int s, error, rcvreserve, sndreserve;
struct sockaddr *saddr;
struct sockaddr_in *sin;
-   struct mbuf *m;
+   struct mbuf *m = NULL, *mopt = NULL;
 
-   if (!(nmp->nm_sotype == SOCK_DGRAM || nmp->nm_sotype == SOCK_STREAM)) {
-   error = EINVAL;
-   goto bad;
-   }
+   if (!(nmp->nm_sotype == SOCK_DGRAM || nmp->nm_sotype == SOCK_STREAM))
+   return (EINVAL);
 
nmp->nm_so = NULL;
saddr = mtod(nmp->nm_nam, struct sockaddr *);
error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, 
nmp->nm_soproto);
-   if (error)
-   goto bad;
+   if (error) {
+   nfs_disconnect(nmp);
+   return (error);
+   }
+
+   /* Allocate mbufs possibly waiting before grabbing the socket lock. */
+   if (nmp->nm_sotype == SOCK_STREAM || saddr->sa_family == AF_INET)
+   MGET(mopt, M_WAIT, MT_SOOPTS);
+   if (saddr->sa_family == AF_INET)
+   MGET(m, M_WAIT, MT_SONAME);
+
so = nmp->nm_so;
+   s = solock(so);
nmp->nm_soflags = so->so_proto->pr_flags;
 
/*
@@ -260,42 +268,29 @@ nfs_connect(struct nfsmount *nmp, struct
 * disclosure through UDP port capture.
 */
if (saddr->sa_family == AF_INET) {
-   struct mbuf *mopt;
int *ip;
 
-   MGET(mopt, M_WAIT, MT_SOOPTS);
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);
-   m_freem(mopt);
if (error)
goto bad;
 
-   MGET(m, M_WAIT, MT_SONAME);
sin = mtod(m, struct sockaddr_in *);
memset(sin, 0, sizeof(*sin));
sin->sin_len = m->m_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = htons(0);
-   s = solock(so);
error = sobind(so, m, &proc0);
-   sounlock(s);
-   m_freem(m);
if (error)
goto bad;
 
-   MGET(mopt, M_WAIT, MT_SOOPTS);
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);
-   m_freem(mopt);
if (error)
goto bad;
}
@@ -310,12 +305,9 @@ nfs_connect(struct nfsmount *nmp, struct
goto bad;
}
} else {
-   s = solock(so);
error = soconnect(so, nmp->nm_nam);
-   if (error) {
-   sounlock(s);
+   if (error)
goto bad;
-   }
 
/*
 * Wait for the connection to complete. Cribbed from the
@@ -328,23 +320,19 @@ nfs_connect(struct nfsmount *nmp, struct
so->so_error == 0 && rep &&
(error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){
so->so_state &= ~SS_ISCONNECTING;
-   sounlock(s);
goto bad;
}
}
if (so->so_error) {
error = so->so_error;
so->so_error = 0;
-   sounlock(s);
goto bad;
}
-   sounlock(s);
}
/*
 * 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))
   

Re: solock() & nfs_connect

2017-08-11 Thread Martin Pieuchot
On 11/08/17(Fri) 20:31, Alexander Bluhm wrote:
> On Fri, Aug 11, 2017 at 01:18:48PM -0400, Martin Pieuchot wrote:
> > Diff below merge all solock()/sounlock() dances inside nfs_connect().
> 
> Now we sleep for memory while holding the lock.  Is this a good
> idea?

As long as a subsystem outside the NET_LOCK() can release memory,
sleeping with the lock held is fine.

>What is the advantage of changing it?

Not introducing multiple sleeping points in a function manipulating a
socket.

> The label names "bad" and "out" are confusing.  Both are bad, but
> bad also does an unlock.

I kept 'bad' which now does the unlock and get rid of the 'out' label,
ok?

Index: nfs/nfs_socket.c
===
RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
retrieving revision 1.122
diff -u -p -r1.122 nfs_socket.c
--- nfs/nfs_socket.c10 Aug 2017 19:20:43 -  1.122
+++ nfs/nfs_socket.c11 Aug 2017 19:31:41 -
@@ -244,9 +244,13 @@ nfs_connect(struct nfsmount *nmp, struct
saddr = mtod(nmp->nm_nam, struct sockaddr *);
error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, 
nmp->nm_soproto);
-   if (error)
-   goto bad;
+   if (error) {
+   nfs_disconnect(nmp);
+   return (error);
+   }
+
so = nmp->nm_so;
+   s = solock(so);
nmp->nm_soflags = so->so_proto->pr_flags;
 
/*
@@ -262,9 +266,7 @@ 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;
 
@@ -275,9 +277,7 @@ nfs_connect(struct nfsmount *nmp, struct
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = htons(0);
-   s = solock(so);
error = sobind(so, m, &proc0);
-   sounlock(s);
m_freem(m);
if (error)
goto bad;
@@ -286,9 +286,7 @@ 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;
}
@@ -303,12 +301,9 @@ nfs_connect(struct nfsmount *nmp, struct
goto bad;
}
} else {
-   s = solock(so);
error = soconnect(so, nmp->nm_nam);
-   if (error) {
-   sounlock(s);
+   if (error)
goto bad;
-   }
 
/*
 * Wait for the connection to complete. Cribbed from the
@@ -321,23 +316,19 @@ nfs_connect(struct nfsmount *nmp, struct
so->so_error == 0 && rep &&
(error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){
so->so_state &= ~SS_ISCONNECTING;
-   sounlock(s);
goto bad;
}
}
if (so->so_error) {
error = so->so_error;
so->so_error = 0;
-   sounlock(s);
goto bad;
}
-   sounlock(s);
}
/*
 * 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);
@@ -372,11 +363,11 @@ nfs_connect(struct nfsmount *nmp, struct
sizeof (u_int32_t)) * 2;
}
error = soreserve(so, sndreserve, rcvreserve);
-   sounlock(s);
if (error)
goto bad;
so->so_rcv.sb_flags |= SB_NOINTR;
so->so_snd.sb_flags |= SB_NOINTR;
+   sounlock(s);
 
/* Initialize other non-zero congestion variables */
nfs_init_rtt(nmp);
@@ -386,6 +377,7 @@ nfs_connect(struct nfsmount *nmp, struct
return (0);
 
 bad:
+   sounlock(s);
nfs_disconnect(nmp);
return (error);
 }



Re: solock() & nfs_connect

2017-08-11 Thread Alexander Bluhm
On Fri, Aug 11, 2017 at 01:18:48PM -0400, Martin Pieuchot wrote:
> Diff below merge all solock()/sounlock() dances inside nfs_connect().

Now we sleep for memory while holding the lock.  Is this a good
idea?  What is the advantage of changing it?

The label names "bad" and "out" are confusing.  Both are bad, but
bad also does an unlock.

bluhm

> Index: nfs/nfs_socket.c
> ===
> RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
> retrieving revision 1.122
> diff -u -p -r1.122 nfs_socket.c
> --- nfs/nfs_socket.c  10 Aug 2017 19:20:43 -  1.122
> +++ nfs/nfs_socket.c  11 Aug 2017 17:14:57 -
> @@ -245,8 +245,9 @@ nfs_connect(struct nfsmount *nmp, struct
>   error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, 
>   nmp->nm_soproto);
>   if (error)
> - goto bad;
> + goto out;
>   so = nmp->nm_so;
> + s = solock(so);
>   nmp->nm_soflags = so->so_proto->pr_flags;
>  
>   /*
> @@ -262,9 +263,7 @@ 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;
>  
> @@ -275,9 +274,7 @@ nfs_connect(struct nfsmount *nmp, struct
>   sin->sin_family = AF_INET;
>   sin->sin_addr.s_addr = INADDR_ANY;
>   sin->sin_port = htons(0);
> - s = solock(so);
>   error = sobind(so, m, &proc0);
> - sounlock(s);
>   m_freem(m);
>   if (error)
>   goto bad;
> @@ -286,9 +283,7 @@ 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;
>   }
> @@ -303,12 +298,9 @@ nfs_connect(struct nfsmount *nmp, struct
>   goto bad;
>   }
>   } else {
> - s = solock(so);
>   error = soconnect(so, nmp->nm_nam);
> - if (error) {
> - sounlock(s);
> + if (error)
>   goto bad;
> - }
>  
>   /*
>* Wait for the connection to complete. Cribbed from the
> @@ -321,23 +313,19 @@ nfs_connect(struct nfsmount *nmp, struct
>   so->so_error == 0 && rep &&
>   (error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){
>   so->so_state &= ~SS_ISCONNECTING;
> - sounlock(s);
>   goto bad;
>   }
>   }
>   if (so->so_error) {
>   error = so->so_error;
>   so->so_error = 0;
> - sounlock(s);
>   goto bad;
>   }
> - sounlock(s);
>   }
>   /*
>* 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);
> @@ -372,11 +360,11 @@ nfs_connect(struct nfsmount *nmp, struct
>   sizeof (u_int32_t)) * 2;
>   }
>   error = soreserve(so, sndreserve, rcvreserve);
> - sounlock(s);
>   if (error)
>   goto bad;
>   so->so_rcv.sb_flags |= SB_NOINTR;
>   so->so_snd.sb_flags |= SB_NOINTR;
> + sounlock(s);
>  
>   /* Initialize other non-zero congestion variables */
>   nfs_init_rtt(nmp);
> @@ -386,6 +374,8 @@ nfs_connect(struct nfsmount *nmp, struct
>   return (0);
>  
>  bad:
> + sounlock(s);
> +out:
>   nfs_disconnect(nmp);
>   return (error);
>  }



solock() & nfs_connect

2017-08-11 Thread Martin Pieuchot
Diff below merge all solock()/sounlock() dances inside nfs_connect().

ok?

Index: nfs/nfs_socket.c
===
RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
retrieving revision 1.122
diff -u -p -r1.122 nfs_socket.c
--- nfs/nfs_socket.c10 Aug 2017 19:20:43 -  1.122
+++ nfs/nfs_socket.c11 Aug 2017 17:14:57 -
@@ -245,8 +245,9 @@ nfs_connect(struct nfsmount *nmp, struct
error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, 
nmp->nm_soproto);
if (error)
-   goto bad;
+   goto out;
so = nmp->nm_so;
+   s = solock(so);
nmp->nm_soflags = so->so_proto->pr_flags;
 
/*
@@ -262,9 +263,7 @@ 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;
 
@@ -275,9 +274,7 @@ nfs_connect(struct nfsmount *nmp, struct
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = htons(0);
-   s = solock(so);
error = sobind(so, m, &proc0);
-   sounlock(s);
m_freem(m);
if (error)
goto bad;
@@ -286,9 +283,7 @@ 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;
}
@@ -303,12 +298,9 @@ nfs_connect(struct nfsmount *nmp, struct
goto bad;
}
} else {
-   s = solock(so);
error = soconnect(so, nmp->nm_nam);
-   if (error) {
-   sounlock(s);
+   if (error)
goto bad;
-   }
 
/*
 * Wait for the connection to complete. Cribbed from the
@@ -321,23 +313,19 @@ nfs_connect(struct nfsmount *nmp, struct
so->so_error == 0 && rep &&
(error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){
so->so_state &= ~SS_ISCONNECTING;
-   sounlock(s);
goto bad;
}
}
if (so->so_error) {
error = so->so_error;
so->so_error = 0;
-   sounlock(s);
goto bad;
}
-   sounlock(s);
}
/*
 * 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);
@@ -372,11 +360,11 @@ nfs_connect(struct nfsmount *nmp, struct
sizeof (u_int32_t)) * 2;
}
error = soreserve(so, sndreserve, rcvreserve);
-   sounlock(s);
if (error)
goto bad;
so->so_rcv.sb_flags |= SB_NOINTR;
so->so_snd.sb_flags |= SB_NOINTR;
+   sounlock(s);
 
/* Initialize other non-zero congestion variables */
nfs_init_rtt(nmp);
@@ -386,6 +374,8 @@ nfs_connect(struct nfsmount *nmp, struct
return (0);
 
 bad:
+   sounlock(s);
+out:
nfs_disconnect(nmp);
return (error);
 }