Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 May 2012 22:01:46 -0700
From:      Vijay Singh <vijju.singh@gmail.com>
To:        freebsd-net@freebsd.org
Subject:   Use of V_tcbinfo lock in tcp_do_segment()
Message-ID:  <CALCNsJSqc%2B4FTZqFJVhhGffVjxzaJaQf=FASrah_=a=WFB_r2w@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Folks, I am trying to understand the need to hold the V_tcbinfo lock
in part of this function [code included below for reference].

At present this causes the socket upcall to be called with the
V_tcbinfo lock held, which I'd like to avoid. We release this lock
right after this section.

Looking at the code, it seems the lock is needed if we were in
FIN_WAIT_2 and tcp_close() the connection. The lock also seems to be
protecting V_twq_2msl.

Would it be an acceptable solution if we deferred calling
socantrecvmore() till after the lock can be dropped (after the swtich
statement). tcp_twstart() can be changed to return tp if the
connections survives, or NULL if it doesn't, much like what
tcp_close() does. Also a new lock could be added to protect the
V_rwq_2msl queue.

If this sounds acceptable, I can generate a patch against -CURRENT. I
would appreciate feedback.

-vijay


relevant code from tcp_do_segment():

        if (thflags & TH_FIN) {
                if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
                        socantrcvmore(so);
                        /*
                         * If connection is half-synchronized
                         * (ie NEEDSYN flag on) then delay ACK,
                         * so it may be piggybacked when SYN is sent.
                         * Otherwise, since we received a FIN then no
                         * more input can be expected, send ACK now.
                         */
                        if (tp->t_flags & TF_NEEDSYN)
                                tp->t_flags |= TF_DELACK;
                        else
                                tp->t_flags |= TF_ACKNOW;
                        tp->rcv_nxt++;
                }
                switch (tp->t_state) {

                /*
                 * In SYN_RECEIVED and ESTABLISHED STATES
                 * enter the CLOSE_WAIT state.
                 */
                case TCPS_SYN_RECEIVED:
                        tp->t_starttime = ticks;
                        /* FALLTHROUGH */
                case TCPS_ESTABLISHED:
                        tp->t_state = TCPS_CLOSE_WAIT;
                        break;

                /*
                 * If still in FIN_WAIT_1 STATE FIN has not been acked so
                 * enter the CLOSING state.
                 */
                case TCPS_FIN_WAIT_1:
                        tp->t_state = TCPS_CLOSING;
                        break;

                /*
                 * In FIN_WAIT_2 state enter the TIME_WAIT state,
                 * starting the time-wait timer, turning off the other
                 * standard timers.
                 */
                case TCPS_FIN_WAIT_2:
                        INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
                        KASSERT(ti_locked == TI_WLOCKED, ("%s: dodata "
                            "TCP_FIN_WAIT_2 ti_locked: %d", __func__,
                            ti_locked));

                        tcp_twstart(tp);
                        INP_INFO_WUNLOCK(&V_tcbinfo);
                        return;
                }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CALCNsJSqc%2B4FTZqFJVhhGffVjxzaJaQf=FASrah_=a=WFB_r2w>