diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
commit | 545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch) | |
tree | e9ce4bc598d06374bda906f18365984bf22a526a /net/unix/af_unix.c | |
parent | 4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (diff) |
Merge with Linux 2.1.55. More bugfixes and goodies from my private
CVS archive.
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index f41213ad6..8622da797 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -24,6 +24,8 @@ * Alan Cox : Started proper garbage collector * Heiko EiBfeldt : Missing verify_area check * Alan Cox : Started POSIXisms + * Andreas Schwab : Replace inode by dentry for proper + * reference counting * * Known differences from reference BSD that was tested: * @@ -229,7 +231,9 @@ static unix_socket *unix_find_socket_byinode(struct inode *i) for (s=unix_socket_table[i->i_ino & 0xF]; s; s=s->next) { - if(s->protinfo.af_unix.inode==i) + struct dentry *dentry = s->protinfo.af_unix.dentry; + + if(dentry && dentry->d_inode == i) { unix_lock(s); return(s); @@ -291,10 +295,10 @@ static void unix_destroy_socket(unix_socket *sk) } } - if(sk->protinfo.af_unix.inode!=NULL) + if(sk->protinfo.af_unix.dentry!=NULL) { - iput(sk->protinfo.af_unix.inode); - sk->protinfo.af_unix.inode=NULL; + dput(sk->protinfo.af_unix.dentry); + sk->protinfo.af_unix.dentry=NULL; } if(!unix_unlock(sk) && atomic_read(&sk->wmem_alloc) == 0) @@ -355,7 +359,7 @@ static int unix_create(struct socket *sock, int protocol) default: return -ESOCKTNOSUPPORT; } - sk = sk_alloc(GFP_KERNEL); + sk = sk_alloc(AF_UNIX, GFP_KERNEL); if (!sk) return -ENOMEM; @@ -363,7 +367,7 @@ static int unix_create(struct socket *sock, int protocol) sk->destruct = unix_destruct_addr; sk->protinfo.af_unix.family=AF_UNIX; - sk->protinfo.af_unix.inode=NULL; + sk->protinfo.af_unix.dentry=NULL; sk->sock_readers=1; /* Us */ sk->protinfo.af_unix.readsem=MUTEX; /* single task reading lock */ sk->mtu=4096; @@ -372,11 +376,6 @@ static int unix_create(struct socket *sock, int protocol) return 0; } -static int unix_dup(struct socket *newsock, struct socket *oldsock) -{ - return unix_create(newsock, 0); -} - static int unix_release(struct socket *sock, struct socket *peer) { unix_socket *sk = sock->sk; @@ -427,7 +426,7 @@ static int unix_autobind(struct socket *sock) addr = kmalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL); if (!addr) return -ENOBUFS; - if (sk->protinfo.af_unix.addr || sk->protinfo.af_unix.inode) + if (sk->protinfo.af_unix.addr || sk->protinfo.af_unix.dentry) { kfree(addr); return -EINVAL; @@ -494,12 +493,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct sock *sk = sock->sk; struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; struct dentry * dentry; - struct inode * inode = NULL; int err; unsigned hash; struct unix_address *addr; - if (sk->protinfo.af_unix.addr || sk->protinfo.af_unix.inode || + if (sk->protinfo.af_unix.addr || sk->protinfo.af_unix.dentry || sunaddr->sun_family != AF_UNIX) return -EINVAL; @@ -516,7 +514,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) /* We slept; recheck ... */ - if (sk->protinfo.af_unix.addr || sk->protinfo.af_unix.inode) + if (sk->protinfo.af_unix.addr || sk->protinfo.af_unix.dentry) { kfree(addr); return -EINVAL; /* Already bound */ @@ -549,16 +547,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) dentry = do_mknod(sunaddr->sun_path, S_IFSOCK|S_IRWXUGO, 0); - err = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - inode = dentry->d_inode; - inode->i_count++; /* HATEFUL - we should use the dentry */ - dput(dentry); - err = 0; - } - - if(err<0) + if (IS_ERR(dentry)) { + err = PTR_ERR(dentry); unix_release_addr(addr); sk->protinfo.af_unix.addr = NULL; if (err==-EEXIST) @@ -567,8 +558,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return err; } unix_remove_socket(sk); - sk->protinfo.af_unix.list = &unix_socket_table[inode->i_ino & 0xF]; - sk->protinfo.af_unix.inode = inode; + sk->protinfo.af_unix.list = &unix_socket_table[dentry->d_inode->i_ino & 0xF]; + sk->protinfo.af_unix.dentry = dentry; unix_insert_socket(sk); return 0; @@ -800,11 +791,8 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) atomic_inc(&sk->protinfo.af_unix.addr->refcnt); newsk->protinfo.af_unix.addr=sk->protinfo.af_unix.addr; } - if (sk->protinfo.af_unix.inode) - { - sk->protinfo.af_unix.inode->i_count++; /* Should use dentry */ - newsk->protinfo.af_unix.inode=sk->protinfo.af_unix.inode; - } + if (sk->protinfo.af_unix.dentry) + newsk->protinfo.af_unix.dentry=dget(sk->protinfo.af_unix.dentry); for (;;) { @@ -1215,8 +1203,15 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, int size if (copied >= target) break; + /* + * POSIX 1003.1g mandates this order. + */ + if (sk->err) + { + up(&sk->protinfo.af_unix.readsem); return sock_error(sk); + } if (sk->shutdown & RCV_SHUTDOWN) break; @@ -1426,7 +1421,7 @@ done: struct proto_ops unix_stream_ops = { AF_UNIX, - unix_dup, + sock_no_dup, unix_release, unix_bind, unix_stream_connect, @@ -1447,12 +1442,12 @@ struct proto_ops unix_stream_ops = { struct proto_ops unix_dgram_ops = { AF_UNIX, - unix_dup, + sock_no_dup, unix_release, unix_bind, unix_dgram_connect, unix_socketpair, - NULL, + sock_no_accept, unix_getname, datagram_poll, unix_ioctl, |