socket lock

Son, Sonny Sonny.Son at netapp.com
Wed Feb 26 22:47:35 UTC 2014


Hi all,

Can somebody explain me how socket data structure-i.e. 'struct socket'-is protected in FreeBSD? It seems that socket is accessed and modified without lock in some places. As an instance, the following code reads and/or modifies various socket fields including so_error without socket lock held:

int
sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio,
    struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
{
        long space, resid;
        int clen = 0, error, dontroute;
#ifdef ZERO_COPY_SOCKETS
        int atomic = sosendallatonce(so) || top;
#endif

        KASSERT(so->so_type == SOCK_DGRAM, ("sodgram_send: !SOCK_DGRAM"));
        KASSERT(so->so_proto->pr_flags & PR_ATOMIC,
            ("sodgram_send: !PR_ATOMIC"));

        if (uio != NULL)
                resid = uio->uio_resid;
        else
                resid = top->m_pkthdr.len;
        /*
         * In theory resid should be unsigned.  However, space must be
         * signed, as it might be less than 0 if we over-committed, and we
         * must use a signed comparison of space and resid.  On the other
         * hand, a negative resid causes us to loop sending 0-length
         * segments to the protocol.
         */
        if (resid < 0) {
                error = EINVAL;
                goto out;
        }

        dontroute =
            (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0;
        if (td != NULL)
                td->td_ru.ru_msgsnd++;
        if (control != NULL)
                clen = control->m_len;

        SOCKBUF_LOCK(&so->so_snd);
        if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
                SOCKBUF_UNLOCK(&so->so_snd);
                error = EPIPE;
                goto out;
        }
        if (so->so_error) {
                error = so->so_error;
                so->so_error = 0;       <=========== we do have socket's send buffer lock but not socket lock (, which is socket recv buffer lock)
                SOCKBUF_UNLOCK(&so->so_snd);
                goto out;
        }

I am sorry if this was already discussed before...

Thank you!


More information about the freebsd-net mailing list