diff options
author | davem <davem> | 2002-01-12 07:48:48 +0000 |
---|---|---|
committer | davem <davem> | 2002-01-12 07:48:48 +0000 |
commit | c8c5dd5a3e180e34183c5f926e6d40de689836f1 (patch) | |
tree | 381200fa018629ec064745a162658b156f8280e8 | |
parent | 373ce4ee3b6ef7c930c52e1a1049cbb55e7e358b (diff) | |
download | netdev-vger-cvs-c8c5dd5a3e180e34183c5f926e6d40de689836f1.tar.gz |
Do not GC embrions about to be attached
to listening socket. Fix from Alexey.
-rw-r--r-- | net/unix/af_unix.c | 11 | ||||
-rw-r--r-- | net/unix/garbage.c | 13 |
2 files changed, 19 insertions, 5 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d79a21f2a..432a23f97 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: af_unix.c,v 1.127 2002-01-11 08:45:37 davem Exp $ + * Version: $Id: af_unix.c,v 1.128 2002-01-12 07:48:48 davem Exp $ * * Fixes: * Linus Torvalds : Assorted bug cures. @@ -483,7 +483,7 @@ static struct sock * unix_create1(struct socket *sock) sk->protinfo.af_unix.dentry=NULL; sk->protinfo.af_unix.mnt=NULL; sk->protinfo.af_unix.lock = RW_LOCK_UNLOCKED; - atomic_set(&sk->protinfo.af_unix.inflight, 0); + atomic_set(&sk->protinfo.af_unix.inflight, sock ? 0 : -1); init_MUTEX(&sk->protinfo.af_unix.readsem);/* single task reading lock */ init_waitqueue_head(&sk->protinfo.af_unix.peer_wait); sk->protinfo.af_unix.list=NULL; @@ -988,7 +988,12 @@ restart: unix_state_wunlock(sk); /* take ten and and send info to listening sock */ - skb_queue_tail(&other->receive_queue,skb); + spin_lock(&other->receive_queue.lock); + __skb_queue_tail(&other->receive_queue,skb); + /* Undo artificially decreased inflight after embrion + * is installed to listening socket. */ + atomic_inc(&newsk->protinfo.af_unix.inflight); + spin_unlock(&other->receive_queue.lock); unix_state_runlock(other); other->data_ready(other, 0); sock_put(other); diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 5abf21e7a..0d035c1a3 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -205,12 +205,21 @@ void unix_gc(void) forall_unix_sockets(i, s) { + int open_count = 0; + /* * If all instances of the descriptor are not * in flight we are in use. + * + * Special case: when socket s is embrion, it may be + * hashed but still not in queue of listening socket. + * In this case (see unix_create1()) we set artificial + * negative inflight counter to close race window. + * It is trick of course and dirty one. */ - if(s->socket && s->socket->file && - file_count(s->socket->file) > atomic_read(&s->protinfo.af_unix.inflight)) + if(s->socket && s->socket->file) + open_count = file_count(s->socket->file); + if (open_count > atomic_read(&s->protinfo.af_unix.inflight)) maybe_unmark_and_push(s); } |