aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2002-01-12 07:48:48 +0000
committerdavem <davem>2002-01-12 07:48:48 +0000
commitc8c5dd5a3e180e34183c5f926e6d40de689836f1 (patch)
tree381200fa018629ec064745a162658b156f8280e8
parent373ce4ee3b6ef7c930c52e1a1049cbb55e7e358b (diff)
downloadnetdev-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.c11
-rw-r--r--net/unix/garbage.c13
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);
}