diff -rup linux-2.6.18.orig/include/net/af_unix.h linux-2.6.18/include/net/af_unix.h --- linux-2.6.18.orig/include/net/af_unix.h 2006-09-19 23:42:06.000000000 -0400 +++ linux-2.6.18/include/net/af_unix.h 2006-10-02 19:42:07.000000000 -0400 @@ -78,7 +78,6 @@ struct unix_sock { struct unix_address *addr; struct dentry *dentry; struct vfsmount *mnt; - struct mutex readlock; struct sock *peer; struct sock *other; struct sock *gc_tree; diff -rup linux-2.6.18.orig/net/unix/af_unix.c linux-2.6.18/net/unix/af_unix.c --- linux-2.6.18.orig/net/unix/af_unix.c 2006-09-19 23:42:06.000000000 -0400 +++ linux-2.6.18/net/unix/af_unix.c 2006-10-06 15:28:44.000000000 -0400 @@ -50,6 +50,8 @@ * Arnaldo C. Melo : Remove MOD_{INC,DEC}_USE_COUNT, * the core infrastructure is doing that * for all net proto families now (2.5.69+) + * Joseph Malicki : Fix SMP race between write/shutdown + * and read. * * * Known differences from reference BSD that was tested: @@ -593,7 +595,6 @@ static struct sock * unix_create1(struct u->mnt = NULL; spin_lock_init(&u->lock); atomic_set(&u->inflight, sock ? 0 : -1); - mutex_init(&u->readlock); /* single task reading lock */ init_waitqueue_head(&u->peer_wait); unix_insert_socket(unix_sockets_unbound, sk); out: @@ -650,7 +651,7 @@ static int unix_autobind(struct socket * struct unix_address * addr; int err; - mutex_lock(&u->readlock); + unix_state_rlock(sk); err = 0; if (u->addr) @@ -687,7 +688,7 @@ retry: spin_unlock(&unix_table_lock); err = 0; -out: mutex_unlock(&u->readlock); +out: unix_state_runlock(sk); return err; } @@ -770,7 +771,7 @@ static int unix_bind(struct socket *sock goto out; addr_len = err; - mutex_lock(&u->readlock); + unix_state_rlock(sk); err = -EINVAL; if (u->addr) @@ -842,7 +843,7 @@ static int unix_bind(struct socket *sock out_unlock: spin_unlock(&unix_table_lock); out_up: - mutex_unlock(&u->readlock); + unix_state_runlock(sk); out: return err; @@ -1572,7 +1573,7 @@ static int unix_dgram_recvmsg(struct kio msg->msg_namelen = 0; - mutex_lock(&u->readlock); + unix_state_rlock(sk); skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) @@ -1628,7 +1629,7 @@ static int unix_dgram_recvmsg(struct kio out_free: skb_free_datagram(sk,skb); out_unlock: - mutex_unlock(&u->readlock); + unix_state_runlock(sk); out: return err; } @@ -1674,7 +1675,6 @@ static int unix_stream_recvmsg(struct ki struct sock_iocb *siocb = kiocb_to_siocb(iocb); struct scm_cookie tmp_scm; struct sock *sk = sock->sk; - struct unix_sock *u = unix_sk(sk); struct sockaddr_un *sunaddr=msg->msg_name; int copied = 0; int check_creds = 0; @@ -1704,7 +1704,7 @@ static int unix_stream_recvmsg(struct ki memset(&tmp_scm, 0, sizeof(tmp_scm)); } - mutex_lock(&u->readlock); + unix_state_rlock(sk); do { @@ -1728,7 +1728,7 @@ static int unix_stream_recvmsg(struct ki err = -EAGAIN; if (!timeo) break; - mutex_unlock(&u->readlock); + unix_state_runlock(sk); timeo = unix_stream_data_wait(sk, timeo); @@ -1736,7 +1736,7 @@ static int unix_stream_recvmsg(struct ki err = sock_intr_errno(timeo); goto out; } - mutex_lock(&u->readlock); + unix_state_rlock(sk); continue; } @@ -1802,7 +1802,7 @@ static int unix_stream_recvmsg(struct ki } } while (size); - mutex_unlock(&u->readlock); + unix_state_runlock(sk); scm_recv(sock, msg, siocb->scm, flags); out: return copied ? : err;