Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.25-rc7 /net/unix/af_unix.c

Filename:/net/unix/af_unix.c
Lines Added:122
Lines Deleted:73
Also changed in: (Previous) 2.6.25-rc6  2.6.25-rc5  2.6.25-rc4  2.6.25-rc3  2.6.25-rc2  2.6.25-rc1-git4 
(Following) 2.6.25-rc8  2.6.25-rc9  2.6.25  2.6.25-git2  2.6.25-git3  2.6.25-git4 

Location
[  2.6.25-rc7
  [  net
    [  unix
       o  af_unix.c

Patch

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 060bba4..b8788fd 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -117,8 +117,6 @@
 #include <net/checksum.h>
 #include <linux/security.h>
 
-int sysctl_unix_max_dgram_qlen __read_mostly = 10;
-
 static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
 static DEFINE_SPINLOCK(unix_table_lock);
 static atomic_t unix_nr_socks = ATOMIC_INIT(0);
@@ -127,32 +125,6 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0);
 
 #define UNIX_ABSTRACT(sk)   (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
 
-static struct sock *first_unix_socket(int *i)
-{
-   for (*i = 0; *i <= UNIX_HASH_SIZE; (*i)++) {
-      if (!hlist_empty(&unix_socket_table[*i]))
-         return __sk_head(&unix_socket_table[*i]);
-   }
-   return NULL;
-}
-
-static struct sock *next_unix_socket(int *i, struct sock *s)
-{
-   struct sock *next = sk_next(s);
-   /* More in this chain? */
-   if (next)
-      return next;
-   /* Look for next non-empty chain. */
-   for ((*i)++; *i <= UNIX_HASH_SIZE; (*i)++) {
-      if (!hlist_empty(&unix_socket_table[*i]))
-         return __sk_head(&unix_socket_table[*i]);
-   }
-   return NULL;
-}
-
-#define forall_unix_sockets(i, s) \
-   for (s = first_unix_socket(&(i)); s; s = next_unix_socket(&(i),(s)))
-
 #ifdef CONFIG_SECURITY_NETWORK
 static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
@@ -270,7 +242,8 @@ static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)
    spin_unlock(&unix_table_lock);
 }
 
-static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname,
+static struct sock *__unix_find_socket_byname(struct net *net,
+                     struct sockaddr_un *sunname,
                      int len, int type, unsigned hash)
 {
    struct sock *s;
@@ -279,6 +252,9 @@ static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname,
    sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
       struct unix_sock *u = unix_sk(s);
 
+      if (s->sk_net != net)
+         continue;
+
       if (u->addr->len == len &&
           !memcmp(u->addr->name, sunname, len))
          goto found;
@@ -288,21 +264,22 @@ found:
    return s;
 }
 
-static inline struct sock *unix_find_socket_byname(struct sockaddr_un *sunname,
+static inline struct sock *unix_find_socket_byname(struct net *net,
+                     struct sockaddr_un *sunname,
                      int len, int type,
                      unsigned hash)
 {
    struct sock *s;
 
    spin_lock(&unix_table_lock);
-   s = __unix_find_socket_byname(sunname, len, type, hash);
+   s = __unix_find_socket_byname(net, sunname, len, type, hash);
    if (s)
       sock_hold(s);
    spin_unlock(&unix_table_lock);
    return s;
 }
 
-static struct sock *unix_find_socket_byinode(struct inode *i)
+static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
 {
    struct sock *s;
    struct hlist_node *node;
@@ -312,6 +289,9 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
           &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
       struct dentry *dentry = unix_sk(s)->dentry;
 
+      if (s->sk_net != net)
+         continue;
+
       if(dentry && dentry->d_inode == i)
       {
          sock_hold(s);
@@ -335,7 +315,7 @@ static void unix_write_space(struct sock *sk)
    if (unix_writable(sk)) {
       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
          wake_up_interruptible_sync(sk->sk_sleep);
-      sk_wake_async(sk, 2, POLL_OUT);
+      sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
    }
    read_unlock(&sk->sk_callback_lock);
 }
@@ -421,7 +401,7 @@ static int unix_release_sock (struct sock *sk, int embrion)
          unix_state_unlock(skpair);
          skpair->sk_state_change(skpair);
          read_lock(&skpair->sk_callback_lock);
-         sk_wake_async(skpair,1,POLL_HUP);
+         sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
          read_unlock(&skpair->sk_callback_lock);
       }
       sock_put(skpair); /* It may now die */
@@ -612,7 +592,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
             &af_unix_sk_receive_queue_lock_key);
 
    sk->sk_write_space   = unix_write_space;
-   sk->sk_max_ack_backlog   = sysctl_unix_max_dgram_qlen;
+   sk->sk_max_ack_backlog   = net->unx.sysctl_max_dgram_qlen;
    sk->sk_destruct      = unix_sock_destructor;
    u     = unix_sk(sk);
    u->dentry = NULL;
@@ -631,9 +611,6 @@ out:
 
 static int unix_create(struct net *net, struct socket *sock, int protocol)
 {
-   if (net != &init_net)
-      return -EAFNOSUPPORT;
-
    if (protocol && protocol != PF_UNIX)
       return -EPROTONOSUPPORT;
 
@@ -677,6 +654,7 @@ static int unix_release(struct socket *sock)
 static int unix_autobind(struct socket *sock)
 {
    struct sock *sk = sock->sk;
+   struct net *net = sk->sk_net;
    struct unix_sock *u = unix_sk(sk);
    static u32 ordernum = 1;
    struct unix_address * addr;
@@ -703,7 +681,7 @@ retry:
    spin_lock(&unix_table_lock);
    ordernum = (ordernum+1)&0xFFFFF;
 
-   if (__unix_find_socket_byname(addr->name, addr->len, sock->type,
+   if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
                   addr->hash)) {
       spin_unlock(&unix_table_lock);
       /* Sanity yield. It is unusual case, but yet... */
@@ -723,7 +701,8 @@ out:   mutex_unlock(&u->readlock);
    return err;
 }
 
-static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
+static struct sock *unix_find_other(struct net *net,
+                struct sockaddr_un *sunname, int len,
                 int type, unsigned hash, int *error)
 {
    struct sock *u;
@@ -739,16 +718,16 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
          goto put_fail;
 
       err = -ECONNREFUSED;
-      if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
+      if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode))
          goto put_fail;
-      u=unix_find_socket_byinode(nd.dentry->d_inode);
+      u = unix_find_socket_byinode(net, nd.path.dentry->d_inode);
       if (!u)
          goto put_fail;
 
       if (u->sk_type == type)
-         touch_atime(nd.mnt, nd.dentry);
+         touch_atime(nd.path.mnt, nd.path.dentry);
 
-      path_release(&nd);
+      path_put(&nd.path);
 
       err=-EPROTOTYPE;
       if (u->sk_type != type) {
@@ -757,7 +736,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
       }
    } else {
       err = -ECONNREFUSED;
-      u=unix_find_socket_byname(sunname, len, type, hash);
+      u=unix_find_socket_byname(net, sunname, len, type, hash);
       if (u) {
          struct dentry *dentry;
          dentry = unix_sk(u)->dentry;
@@ -769,7 +748,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
    return u;
 
 put_fail:
-   path_release(&nd);
+   path_put(&nd.path);
 fail:
    *error=err;
    return NULL;
@@ -779,6 +758,7 @@ fail:
 static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
    struct sock *sk = sock->sk;
+   struct net *net = sk->sk_net;
    struct unix_sock *u = unix_sk(sk);
    struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
    struct dentry * dentry = NULL;
@@ -839,12 +819,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        */
       mode = S_IFSOCK |
              (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
-      err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
+      err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
       if (err)
          goto out_mknod_dput;
-      mutex_unlock(&nd.dentry->d_inode->i_mutex);
-      dput(nd.dentry);
-      nd.dentry = dentry;
+      mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+      dput(nd.path.dentry);
+      nd.path.dentry = dentry;
 
       addr->hash = UNIX_HASH_SIZE;
    }
@@ -853,7 +833,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
    if (!sunaddr->sun_path[0]) {
       err = -EADDRINUSE;
-      if (__unix_find_socket_byname(sunaddr, addr_len,
+      if (__unix_find_socket_byname(net, sunaddr, addr_len,
                      sk->sk_type, hash)) {
          unix_release_addr(addr);
          goto out_unlock;
@@ -862,8 +842,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
       list = &unix_socket_table[addr->hash];
    } else {
       list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
-      u->dentry = nd.dentry;
-      u->mnt    = nd.mnt;
+      u->dentry = nd.path.dentry;
+      u->mnt    = nd.path.mnt;
    }
 
    err = 0;
@@ -881,8 +861,8 @@ out:
 out_mknod_dput:
    dput(dentry);
 out_mknod_unlock:
-   mutex_unlock(&nd.dentry->d_inode->i_mutex);
-   path_release(&nd);
+   mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+   path_put(&nd.path);
 out_mknod_parent:
    if (err==-EEXIST)
       err=-EADDRINUSE;
@@ -919,6 +899,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
                int alen, int flags)
 {
    struct sock *sk = sock->sk;
+   struct net *net = sk->sk_net;
    struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
    struct sock *other;
    unsigned hash;
@@ -935,7 +916,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
          goto out;
 
 restart:
-      other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
+      other=unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
       if (!other)
          goto out;
 
@@ -1015,6 +996,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 {
    struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
    struct sock *sk = sock->sk;
+   struct net *net = sk->sk_net;
    struct unix_sock *u = unix_sk(sk), *newu, *otheru;
    struct sock *newsk = NULL;
    struct sock *other = NULL;
@@ -1054,7 +1036,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 
 restart:
    /*  Find listening sock. */
-   other = unix_find_other(sunaddr, addr_len, sk->sk_type, hash, &err);
+   other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
    if (!other)
       goto out;
 
@@ -1330,6 +1312,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 {
    struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
    struct sock *sk = sock->sk;
+   struct net *net = sk->sk_net;
    struct unix_sock *u = unix_sk(sk);
    struct sockaddr_un *sunaddr=msg->msg_name;
    struct sock *other = NULL;
@@ -1393,7 +1376,7 @@ restart:
       if (sunaddr == NULL)
          goto out_free;
 
-      other = unix_find_other(sunaddr, namelen, sk->sk_type,
+      other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
                hash, &err);
       if (other==NULL)
          goto out_free;
@@ -1915,9 +1898,9 @@ static int unix_shutdown(struct socket *sock, int mode)
          other->sk_state_change(other);
          read_lock(&other->sk_callback_lock);
          if (peer_mode == SHUTDOWN_MASK)
-            sk_wake_async(other,1,POLL_HUP);
+            sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
          else if (peer_mode & RCV_SHUTDOWN)
-            sk_wake_async(other,1,POLL_IN);
+            sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
          read_unlock(&other->sk_callback_lock);
       }
       if (other)
@@ -2006,12 +1989,41 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl
 
 
 #ifdef CONFIG_PROC_FS
-static struct sock *unix_seq_idx(int *iter, loff_t pos)
+static struct sock *first_unix_socket(int *i)
+{
+   for (*i = 0; *i <= UNIX_HASH_SIZE; (*i)++) {
+      if (!hlist_empty(&unix_socket_table[*i]))
+         return __sk_head(&unix_socket_table[*i]);
+   }
+   return NULL;
+}
+
+static struct sock *next_unix_socket(int *i, struct sock *s)
+{
+   struct sock *next = sk_next(s);
+   /* More in this chain? */
+   if (next)
+      return next;
+   /* Look for next non-empty chain. */
+   for ((*i)++; *i <= UNIX_HASH_SIZE; (*i)++) {
+      if (!hlist_empty(&unix_socket_table[*i]))
+         return __sk_head(&unix_socket_table[*i]);
+   }
+   return NULL;
+}
+
+struct unix_iter_state {
+   struct seq_net_private p;
+   int i;
+};
+static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
 {
    loff_t off = 0;
    struct sock *s;
 
-   for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) {
+   for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) {
+      if (s->sk_net != iter->p.net)
+         continue;
       if (off == pos)
          return s;
       ++off;
@@ -2021,21 +2033,30 @@ static struct sock *unix_seq_idx(int *iter, loff_t pos)
 
 
 static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
+   __acquires(unix_table_lock)
 {
+   struct unix_iter_state *iter = seq->private;
    spin_lock(&unix_table_lock);
-   return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1);
+   return *pos ? unix_seq_idx(iter, *pos - 1) : ((void *) 1);
 }
 
 static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
+   struct unix_iter_state *iter = seq->private;
+   struct sock *sk = v;
    ++*pos;
 
    if (v == (void *)1)
-      return first_unix_socket(seq->private);
-   return next_unix_socket(seq->private, v);
+      sk = first_unix_socket(&iter->i);
+   else
+      sk = next_unix_socket(&iter->i, sk);
+   while (sk && (sk->sk_net != iter->p.net))
+      sk = next_unix_socket(&iter->i, sk);
+   return sk;
 }
 
 static void unix_seq_stop(struct seq_file *seq, void *v)
+   __releases(unix_table_lock)
 {
    spin_unlock(&unix_table_lock);
 }
@@ -2094,7 +2115,8 @@ static const struct seq_operations unix_seq_ops = {
 
 static int unix_seq_open(struct inode *inode, struct file *file)
 {
-   return seq_open_private(file, &unix_seq_ops, sizeof(int));
+   return seq_open_net(inode, file, &unix_seq_ops,
+             sizeof(struct unix_iter_state));
 }
 
 static const struct file_operations unix_seq_fops = {
@@ -2102,7 +2124,7 @@ static const struct file_operations unix_seq_fops = {
    .open      = unix_seq_open,
    .read      = seq_read,
    .llseek      = seq_lseek,
-   .release   = seq_release_private,
+   .release   = seq_release_net,
 };
 
 #endif
@@ -2113,6 +2135,37 @@ static struct net_proto_family unix_family_ops = {
    .owner   = THIS_MODULE,
 };
 
+
+static int unix_net_init(struct net *net)
+{
+   int error = -ENOMEM;
+
+   net->unx.sysctl_max_dgram_qlen = 10;
+   if (unix_sysctl_register(net))
+      goto out;
+
+#ifdef CONFIG_PROC_FS
+   if (!proc_net_fops_create(net, "unix", 0, &unix_seq_fops)) {
+      unix_sysctl_unregister(net);
+      goto out;
+   }
+#endif
+   error = 0;
+out:
+   return 0;
+}
+
+static void unix_net_exit(struct net *net)
+{
+   unix_sysctl_unregister(net);
+   proc_net_remove(net, "unix");
+}
+
+static struct pernet_operations unix_net_ops = {
+   .init = unix_net_init,
+   .exit = unix_net_exit,
+};
+
 static int __init af_unix_init(void)
 {
    int rc = -1;
@@ -2128,10 +2181,7 @@ static int __init af_unix_init(void)
    }
 
    sock_register(&unix_family_ops);
-#ifdef CONFIG_PROC_FS
-   proc_net_fops_create(&init_net, "unix", 0, &unix_seq_fops);
-#endif
-   unix_sysctl_register();
+   register_pernet_subsys(&unix_net_ops);
 out:
    return rc;
 }
@@ -2139,9 +2189,8 @@ out:
 static void __exit af_unix_exit(void)
 {
    sock_unregister(PF_UNIX);
-   unix_sysctl_unregister();
-   proc_net_remove(&init_net, "unix");
    proto_unregister(&unix_proto);
+   unregister_pernet_subsys(&unix_net_ops);
 }
 
 module_init(af_unix_init);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.