Nothing special, just get assign `inp' and `tp' from passed socket. I
want to do this before (*pru_usrreq)() split to avoid huge code
duplication.

We have "tp might get 0 when using socket splicing" commentary. I
checked where we set `inp_ppcb' to NULL and found, tcp_close() is the
only place, and the following in_pcbdetach() sets `so_pcb' to NULL. So
this commentary looks wrong, because we can't have TCP sockets without
TCP pcb attached.

This diff works fine with sys/kern/sosplice test.

ok?

Index: sys/netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.187
diff -u -p -r1.187 tcp_usrreq.c
--- sys/netinet/tcp_usrreq.c    15 Aug 2022 09:11:39 -0000      1.187
+++ sys/netinet/tcp_usrreq.c    15 Aug 2022 10:51:18 -0000
@@ -142,6 +142,33 @@ struct     inpcbtable tcbtable;
 int    tcp_fill_info(struct tcpcb *, struct socket *, struct mbuf *);
 int    tcp_ident(void *, size_t *, void *, size_t, int);
 
+static inline int tcp_sogetpcb(struct socket *, struct inpcb **,
+                      struct tcpcb **);
+
+static inline int
+tcp_sogetpcb(struct socket *so, struct inpcb **rinp, struct tcpcb **rtp)
+{
+       struct inpcb *inp;
+
+       /*
+        * When a TCP is attached to a socket, then there will be
+        * a (struct inpcb) pointed at by the socket, and this
+        * structure will point at a subsidiary (struct tcpcb).
+        */
+       if ((inp = sotoinpcb(so)) == NULL) {
+               if (so->so_error)
+                       return so->so_error;
+               return EINVAL;
+       }
+
+       *rinp = inp;
+       *rtp = intotcpcb(inp);
+
+       KASSERT(*rtp != NULL);
+
+       return 0;
+}
+
 /*
  * Process a TCP user request for TCP tb.  If this is a send request
  * then m is the mbuf chain of send data.  If this is a timer expiration
@@ -153,7 +180,7 @@ tcp_usrreq(struct socket *so, int req, s
     struct mbuf *control, struct proc *p)
 {
        struct inpcb *inp;
-       struct tcpcb *otp = NULL, *tp = NULL;
+       struct tcpcb *otp = NULL, *tp;
        int error = 0;
        short ostate;
 
@@ -175,22 +202,9 @@ tcp_usrreq(struct socket *so, int req, s
                goto release;
        }
 
-       inp = sotoinpcb(so);
-       /*
-        * When a TCP is attached to a socket, then there will be
-        * a (struct inpcb) pointed at by the socket, and this
-        * structure will point at a subsidiary (struct tcpcb).
-        */
-       if (inp == NULL) {
-               error = so->so_error;
-               if (error == 0)
-                       error = EINVAL;
-               goto release;
-       }
-       tp = intotcpcb(inp);
-       /* tp might get 0 when using socket splicing */
-       if (tp == NULL)
+       if ((error = tcp_sogetpcb(so, &inp, &tp)))
                goto release;
+
        if (so->so_options & SO_DEBUG) {
                otp = tp;
                ostate = tp->t_state;
@@ -739,28 +753,15 @@ int
 tcp_detach(struct socket *so)
 {
        struct inpcb *inp;
-       struct tcpcb *otp = NULL, *tp = NULL;
+       struct tcpcb *otp = NULL, *tp;
        int error = 0;
        short ostate;
 
        soassertlocked(so);
 
-       inp = sotoinpcb(so);
-       /*
-        * When a TCP is attached to a socket, then there will be
-        * a (struct inpcb) pointed at by the socket, and this
-        * structure will point at a subsidiary (struct tcpcb).
-        */
-       if (inp == NULL) {
-               error = so->so_error;
-               if (error == 0)
-                       error = EINVAL;
+       if ((error = tcp_sogetpcb(so, &inp, &tp)))
                return (error);
-       }
-       tp = intotcpcb(inp);
-       /* tp might get 0 when using socket splicing */
-       if (tp == NULL)
-               return (0);
+
        if (so->so_options & SO_DEBUG) {
                otp = tp;
                ostate = tp->t_state;

Reply via email to