]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/commit
MFC 296178
authorsephe <sephe@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>
Wed, 15 Jun 2016 05:16:37 +0000 (05:16 +0000)
committersephe <sephe@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>
Wed, 15 Jun 2016 05:16:37 +0000 (05:16 +0000)
commit106ae4078642dd30624e9f6bfccf6747c9a88969
treedb9d553fec5c0b0092a3037ec5d5549fe2da5ae3
parentcb2a10a66c6314051a1092a3dfed8502c579027b
MFC 296178

    buf_ring/drbr: Add buf_ring_peek_clear_sc and use it in drbr_peek

    Unlike buf_ring_peek, it only supports single consumer mode, and it
    clears the cons_head if DEBUG_BUFRING/INVARIANTS is defined.

    The normal use case of drbr_peek for network drivers is:

    m = drbr_peek(br);
    err = hw_spec_encap(&m); /* could m_defrag/m_collapse */
    (*)
    if (err) {
        if (m == NULL)
            drbr_advance(br);
        else
            drbr_putback(br, m);
        /* break the loop */
    }
    drbr_advance(br);

    The race is:
    If hw_spec_encap() m_defrag or m_collapse the mbuf, i.e. the old mbuf
    was freed, or like the Hyper-V's network driver, that transmission-
    done does not even require the TX lock; then on the other CPU at the
    (*) time, the freed mbuf could be recycled and being drbr_enqueue even
    before the current CPU had the chance to call drbr_{advance,putback}.
    This triggers a panic in drbr_enqueue duplicated element check, if
    DEBUG_BUFRING/INVARIANTS is defined.

    Use buf_ring_peek_clear_sc() in drbr_peek() to fix the above race.

    This change is a NO-OP, if neither DEBUG_BUFRING nor INVARIANTS are
    defined.

    MFC after:  1 week
    Sponsored by:       Microsoft OSTC
    Differential Revision:      https://reviews.freebsd.org/D5416

git-svn-id: svn://svn.freebsd.org/base/stable/10@301913 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
sys/net/if_var.h
sys/sys/buf_ring.h