On Jul 29, 2009, at 1:10 AM, Pawel Jakub Dawidek wrote:

On Tue, Jul 28, 2009 at 02:09:07PM +0000, Randall Stewart wrote:
Author: rrs
Date: Tue Jul 28 14:09:06 2009
New Revision: 195918
URL: http://svn.freebsd.org/changeset/base/195918

Log:
 Turns out that when a receiver forwards through its TNS's the
 processing code holds the read lock (when processing a
 FWD-TSN for pr-sctp). If it finds stranded data that
 can be given to the application, it calls sctp_add_to_readq().
 The readq function also grabs this lock. So if INVAR is on
 we get a double recurse on a non-recursive lock and panic.

 This fix will change it so that readq() function gets a
 flag to tell if the lock is held, if so then it does not
 get the lock.

 Approved by:   r...@freebsd.org (Kostik Belousov)
 MFC after:     1 week
[...]
        sctp_add_to_readq(stcb->sctp_ep, stcb, control,
-           &stcb->sctp_socket->so_rcv, 1, so_locked);
+ &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
[...]
@@ -4301,6 +4306,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp
    struct sctp_queued_to_read *control,
    struct sockbuf *sb,
    int end,
+    int inp_read_lock_held,
    int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    SCTP_UNUSED
@@ -4321,7 +4327,8 @@ sctp_add_to_readq(struct sctp_inpcb *inp
#endif
                return;
        }
-       SCTP_INP_READ_LOCK(inp);
+       if (inp_read_lock_held == 0)

It would be a bit cleaner to compare with SCTP_READ_LOCK_NOT_HELD here,
instead of 0.

I suppose so ;-)



+               SCTP_INP_READ_LOCK(inp);
        if (!(control->spec_flags & M_NOTIFICATION)) {
                atomic_add_int(&inp->total_recvs, 1);
                if (!control->do_not_ref_stcb) {
@@ -4362,14 +4369,16 @@ sctp_add_to_readq(struct sctp_inpcb *inp
                control->tail_mbuf = prev;
        } else {
                /* Everything got collapsed out?? */
-               SCTP_INP_READ_UNLOCK(inp);
+               if (inp_read_lock_held == 0)
+                       SCTP_INP_READ_UNLOCK(inp);
                return;
        }
        if (end) {
                control->end_added = 1;
        }
        TAILQ_INSERT_TAIL(&inp->read_queue, control, next);
-       SCTP_INP_READ_UNLOCK(inp);
+       if (inp_read_lock_held == 0)
+               SCTP_INP_READ_UNLOCK(inp);
        if (inp && inp->sctp_socket) {
                if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
                        SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);

Instead of using additional argument to the sctp_add_to_readq()
function, wouldn't it be sufficient to just check with mtx_owned(9) if
the lock is already held?

Hmm... I suppose one could go that way... but traditionally upper code as
told the lower code that it holds/does not hold the lock. This is true
in quite a few other functions...

R


--
Pawel Jakub Dawidek                       http://www.wheel.pl
p...@freebsd.org                           http://www.FreeBSD.org
FreeBSD committer                         Am I Evil? Yes, I Am!

------------------------------
Randall Stewart
803-317-4952 (cell)
803-345-0391(direct)

_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to