patch-2.3.99-pre7 linux/net/unix/af_unix.c
Next file: linux/net/x25/x25_timer.c
Previous file: linux/net/sunrpc/svcauth.c
Back to the patch index
Back to the overall index
- Lines: 176
- Date:
Mon May 8 22:21:58 2000
- Orig file:
v2.3.99-pre6/linux/net/unix/af_unix.c
- Orig date:
Wed Apr 26 16:34:10 2000
diff -u --recursive --new-file v2.3.99-pre6/linux/net/unix/af_unix.c linux/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.94 2000/04/25 04:13:35 davem Exp $
+ * Version: $Id: af_unix.c,v 1.95 2000/05/09 04:48:37 davem Exp $
*
* Fixes:
* Linus Torvalds : Assorted bug cures.
@@ -330,6 +330,7 @@
static int unix_release_sock (unix_socket *sk, int embrion)
{
struct dentry *dentry;
+ struct vfsmount *mnt;
unix_socket *skpair;
struct sk_buff *skb;
int state;
@@ -342,6 +343,8 @@
sk->shutdown = SHUTDOWN_MASK;
dentry = sk->protinfo.af_unix.dentry;
sk->protinfo.af_unix.dentry=NULL;
+ mnt = sk->protinfo.af_unix.mnt;
+ sk->protinfo.af_unix.mnt=NULL;
state = sk->state;
sk->state = TCP_CLOSE;
unix_state_wunlock(sk);
@@ -379,6 +382,7 @@
if (dentry) {
lock_kernel();
dput(dentry);
+ mntput(mnt);
unlock_kernel();
}
@@ -459,6 +463,7 @@
sk->max_ack_backlog = sysctl_unix_max_dgram_qlen;
sk->destruct = unix_sock_destructor;
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);
init_MUTEX(&sk->protinfo.af_unix.readsem);/* single task reading lock */
@@ -564,30 +569,30 @@
int type, unsigned hash, int *error)
{
unix_socket *u;
- struct dentry *dentry;
- int err;
+ struct nameidata nd;
+ int err = 0;
if (sunname->sun_path[0]) {
/* Do not believe to VFS, grab kernel lock */
lock_kernel();
- dentry = lookup_dentry(sunname->sun_path,LOOKUP_POSITIVE);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry)) {
+ if (path_init(sunname->sun_path, LOOKUP_POSITIVE, &nd))
+ err = path_walk(sunname->sun_path, &nd);
+ if (err) {
unlock_kernel();
goto fail;
}
- err = permission(dentry->d_inode,MAY_WRITE);
+ err = permission(nd.dentry->d_inode,MAY_WRITE);
if (err)
goto put_fail;
err = -ECONNREFUSED;
- if (!S_ISSOCK(dentry->d_inode->i_mode))
+ if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
goto put_fail;
- u=unix_find_socket_byinode(dentry->d_inode);
+ u=unix_find_socket_byinode(nd.dentry->d_inode);
if (!u)
goto put_fail;
- dput(dentry);
+ path_release(&nd);
unlock_kernel();
err=-EPROTOTYPE;
@@ -604,7 +609,7 @@
return u;
put_fail:
- dput(dentry);
+ path_release(&nd);
unlock_kernel();
fail:
*error=err;
@@ -617,6 +622,7 @@
struct sock *sk = sock->sk;
struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
struct dentry * dentry = NULL;
+ struct nameidata nd;
int err;
unsigned hash;
struct unix_address *addr;
@@ -654,15 +660,29 @@
if (sunaddr->sun_path[0]) {
lock_kernel();
- dentry = do_mknod(sunaddr->sun_path, S_IFSOCK|sock->inode->i_mode, 0);
- if (IS_ERR(dentry)) {
- err = PTR_ERR(dentry);
- unlock_kernel();
- if (err==-EEXIST)
- err=-EADDRINUSE;
- unix_release_addr(addr);
- goto out_up;
- }
+ err = 0;
+ if (path_init(sunaddr->sun_path, LOOKUP_PARENT, &nd))
+ err = path_walk(sunaddr->sun_path, &nd);
+ if (err)
+ goto out_mknod_parent;
+ err = -EEXIST;
+ if (nd.last_type != LAST_NORM)
+ goto out_mknod;
+ down(&nd.dentry->d_inode->i_sem);
+ dentry = lookup_hash(&nd.last, nd.dentry);
+ err = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto out_mknod_unlock;
+ err = -ENOENT;
+ if (nd.last.name[nd.last.len] && !dentry->d_inode)
+ goto out_mknod_dput;
+ err = vfs_mknod(nd.dentry->d_inode, dentry,
+ S_IFSOCK|sock->inode->i_mode, 0);
+ if (err)
+ goto out_mknod_dput;
+ up(&nd.dentry->d_inode->i_sem);
+ dput(nd.dentry);
+ nd.dentry = dentry;
unlock_kernel();
addr->hash = UNIX_HASH_SIZE;
@@ -681,7 +701,8 @@
list = &unix_socket_table[addr->hash];
} else {
list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
- sk->protinfo.af_unix.dentry = dentry;
+ sk->protinfo.af_unix.dentry = nd.dentry;
+ sk->protinfo.af_unix.mnt = nd.mnt;
}
err = 0;
@@ -695,6 +716,19 @@
up(&sk->protinfo.af_unix.readsem);
out:
return err;
+
+out_mknod_dput:
+ dput(dentry);
+out_mknod_unlock:
+ up(&nd.dentry->d_inode->i_sem);
+out_mknod:
+ path_release(&nd);
+out_mknod_parent:
+ unlock_kernel();
+ if (err==-EEXIST)
+ err=-EADDRINUSE;
+ unix_release_addr(addr);
+ goto out_up;
}
static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
@@ -904,6 +938,7 @@
/* Damn, even dget is not SMP safe. It becomes ridiculous... */
lock_kernel();
newsk->protinfo.af_unix.dentry=dget(other->protinfo.af_unix.dentry);
+ newsk->protinfo.af_unix.mnt=mntget(other->protinfo.af_unix.mnt);
unlock_kernel();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)