Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Feb 2014 22:47:16 +0000
From:      "Son, Sonny" <Sonny.Son@netapp.com>
To:        "freebsd-net (freebsd-net@freebsd.org)" <freebsd-net@freebsd.org>
Subject:   socket lock
Message-ID:  <3967D1AB1B4E6F4CA4E2329EEB83ED3E30D8C3A7@SACEXCMBX03-PRD.hq.netapp.com>

next in thread | raw e-mail | index | archive | help
Hi all,

Can somebody explain me how socket data structure-i.e. 'struct socket'-is p=
rotected in FreeBSD? It seems that socket is accessed and modified without =
lock in some places. As an instance, the following code reads and/or modifi=
es 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 =3D 0, error, dontroute;
#ifdef ZERO_COPY_SOCKETS
        int atomic =3D sosendallatonce(so) || top;
#endif

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

        if (uio !=3D NULL)
                resid =3D uio->uio_resid;
        else
                resid =3D 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 =3D EINVAL;
                goto out;
        }

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

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

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

Thank you!



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3967D1AB1B4E6F4CA4E2329EEB83ED3E30D8C3A7>