FRV: Reinstate null behaviour for the GDB remote protocol 'p' command
[safe/jmp/linux-2.6] / net / tipc / socket.c
index ddcb2a7..66e889b 100644 (file)
@@ -40,9 +40,9 @@
 #include <linux/socket.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
+#include <linux/gfp.h>
 #include <asm/string.h>
 #include <asm/atomic.h>
 #include <net/sock.h>
@@ -63,6 +63,7 @@
 struct tipc_sock {
        struct sock sk;
        struct tipc_port *p;
+       struct tipc_portid peer_name;
 };
 
 #define tipc_sk(sk) ((struct tipc_sock *)(sk))
@@ -176,6 +177,7 @@ static void reject_rx_queue(struct sock *sk)
  * @net: network namespace (must be default network)
  * @sock: pre-allocated socket structure
  * @protocol: protocol indicator (must be 0)
+ * @kern: caused by kernel or by userspace?
  *
  * This routine creates additional data structures used by the TIPC socket,
  * initializes them, and links them together.
@@ -183,7 +185,8 @@ static void reject_rx_queue(struct sock *sk)
  * Returns 0 on success, errno otherwise
  */
 
-static int tipc_create(struct net *net, struct socket *sock, int protocol)
+static int tipc_create(struct net *net, struct socket *sock, int protocol,
+                      int kern)
 {
        const struct proto_ops *ops;
        socket_state state;
@@ -192,7 +195,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
 
        /* Validate arguments */
 
-       if (net != &init_net)
+       if (!net_eq(net, &init_net))
                return -EAFNOSUPPORT;
 
        if (unlikely(protocol != 0))
@@ -377,27 +380,29 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
  * @sock: socket structure
  * @uaddr: area for returned socket address
  * @uaddr_len: area for returned length of socket address
- * @peer: 0 to obtain socket name, 1 to obtain peer socket name
+ * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID
  *
  * Returns 0 on success, errno otherwise
  *
- * NOTE: This routine doesn't need to take the socket lock since it doesn't
- *       access any non-constant socket information.
+ * NOTE: This routine doesn't need to take the socket lock since it only
+ *       accesses socket information that is unchanging (or which changes in
+ *      a completely predictable manner).
  */
 
 static int get_name(struct socket *sock, struct sockaddr *uaddr,
                    int *uaddr_len, int peer)
 {
        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
-       u32 portref = tipc_sk_port(sock->sk)->ref;
-       u32 res;
+       struct tipc_sock *tsock = tipc_sk(sock->sk);
 
        if (peer) {
-               res = tipc_peer(portref, &addr->addr.id);
-               if (res)
-                       return res;
+               if ((sock->state != SS_CONNECTED) &&
+                       ((peer != 2) || (sock->state != SS_DISCONNECTING)))
+                       return -ENOTCONN;
+               addr->addr.id.ref = tsock->peer_name.ref;
+               addr->addr.id.node = tsock->peer_name.node;
        } else {
-               tipc_ownidentity(portref, &addr->addr.id);
+               tipc_ownidentity(tsock->p->ref, &addr->addr.id);
        }
 
        *uaddr_len = sizeof(*addr);
@@ -441,7 +446,7 @@ static unsigned int poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk;
        u32 mask;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       poll_wait(file, sk_sleep(sk), wait);
 
        if (!skb_queue_empty(&sk->sk_receive_queue) ||
            (sock->state == SS_UNCONNECTED) ||
@@ -586,7 +591,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
                        break;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                                               !tport->congested);
                lock_sock(sk);
                if (res)
@@ -645,7 +650,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
                        break;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                        (!tport->congested || !tport->connected));
                lock_sock(sk);
                if (res)
@@ -766,18 +771,17 @@ exit:
 
 static int auto_connect(struct socket *sock, struct tipc_msg *msg)
 {
-       struct tipc_port *tport = tipc_sk_port(sock->sk);
-       struct tipc_portid peer;
+       struct tipc_sock *tsock = tipc_sk(sock->sk);
 
        if (msg_errcode(msg)) {
                sock->state = SS_DISCONNECTING;
                return -ECONNREFUSED;
        }
 
-       peer.ref = msg_origport(msg);
-       peer.node = msg_orignode(msg);
-       tipc_connect2port(tport->ref, &peer);
-       tipc_set_portimportance(tport->ref, msg_importance(msg));
+       tsock->peer_name.ref = msg_origport(msg);
+       tsock->peer_name.node = msg_orignode(msg);
+       tipc_connect2port(tsock->p->ref, &tsock->peer_name);
+       tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
        sock->state = SS_CONNECTED;
        return 0;
 }
@@ -927,7 +931,7 @@ restart:
                        goto exit;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                        (!skb_queue_empty(&sk->sk_receive_queue) ||
                         (sock->state == SS_DISCONNECTING)));
                lock_sock(sk);
@@ -1060,7 +1064,7 @@ restart:
                        goto exit;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                        (!skb_queue_empty(&sk->sk_receive_queue) ||
                         (sock->state == SS_DISCONNECTING)));
                lock_sock(sk);
@@ -1132,13 +1136,11 @@ restart:
 
        /* Loop around if more data is required */
 
-       if ((sz_copied < buf_len)    /* didn't get all requested data */
-           && (!skb_queue_empty(&sk->sk_receive_queue) ||
-               (flags & MSG_WAITALL))
-                                    /* ... and more is ready or required */
-           && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */
-           && (!err)                /* ... and haven't reached a FIN */
-           )
+       if ((sz_copied < buf_len) &&    /* didn't get all requested data */
+           (!skb_queue_empty(&sk->sk_receive_queue) ||
+            (flags & MSG_WAITALL)) &&  /* and more is ready or required */
+           (!(flags & MSG_PEEK)) &&    /* and aren't just peeking at data */
+           (!err))                     /* and haven't reached a FIN */
                goto restart;
 
 exit:
@@ -1269,8 +1271,8 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
                tipc_disconnect_port(tipc_sk_port(sk));
        }
 
-       if (waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
+       if (waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible(sk_sleep(sk));
        return TIPC_OK;
 }
 
@@ -1320,8 +1322,10 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
        if (!sock_owned_by_user(sk)) {
                res = filter_rcv(sk, buf);
        } else {
-               sk_add_backlog(sk, buf);
-               res = TIPC_OK;
+               if (sk_add_backlog(sk, buf))
+                       res = TIPC_ERR_OVERLOAD;
+               else
+                       res = TIPC_OK;
        }
        bh_unlock_sock(sk);
 
@@ -1339,8 +1343,8 @@ static void wakeupdispatch(struct tipc_port *tport)
 {
        struct sock *sk = (struct sock *)tport->usr_handle;
 
-       if (waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
+       if (waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible(sk_sleep(sk));
 }
 
 /**
@@ -1422,7 +1426,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
        /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
 
        release_sock(sk);
-       res = wait_event_interruptible_timeout(*sk->sk_sleep,
+       res = wait_event_interruptible_timeout(*sk_sleep(sk),
                        (!skb_queue_empty(&sk->sk_receive_queue) ||
                        (sock->state != SS_CONNECTING)),
                        sk->sk_rcvtimeo);
@@ -1517,7 +1521,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
                        goto exit;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                                (!skb_queue_empty(&sk->sk_receive_queue)));
                lock_sock(sk);
                if (res)
@@ -1526,12 +1530,12 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
 
        buf = skb_peek(&sk->sk_receive_queue);
 
-       res = tipc_create(sock_net(sock->sk), new_sock, 0);
+       res = tipc_create(sock_net(sock->sk), new_sock, 0, 0);
        if (!res) {
                struct sock *new_sk = new_sock->sk;
-               struct tipc_port *new_tport = tipc_sk_port(new_sk);
+               struct tipc_sock *new_tsock = tipc_sk(new_sk);
+               struct tipc_port *new_tport = new_tsock->p;
                u32 new_ref = new_tport->ref;
-               struct tipc_portid id;
                struct tipc_msg *msg = buf_msg(buf);
 
                lock_sock(new_sk);
@@ -1545,9 +1549,9 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
 
                /* Connect new socket to it's peer */
 
-               id.ref = msg_origport(msg);
-               id.node = msg_orignode(msg);
-               tipc_connect2port(new_ref, &id);
+               new_tsock->peer_name.ref = msg_origport(msg);
+               new_tsock->peer_name.node = msg_orignode(msg);
+               tipc_connect2port(new_ref, &new_tsock->peer_name);
                new_sock->state = SS_CONNECTED;
 
                tipc_set_portimportance(new_ref, msg_importance(msg));
@@ -1628,8 +1632,8 @@ restart:
                /* Discard any unreceived messages; wake up sleeping tasks */
 
                discard_rx_queue(sk);
-               if (waitqueue_active(sk->sk_sleep))
-                       wake_up_interruptible(sk->sk_sleep);
+               if (waitqueue_active(sk_sleep(sk)))
+                       wake_up_interruptible(sk_sleep(sk));
                res = 0;
                break;
 
@@ -1656,7 +1660,7 @@ restart:
  */
 
 static int setsockopt(struct socket *sock,
-                     int lvl, int opt, char __user *ov, int ol)
+                     int lvl, int opt, char __user *ov, unsigned int ol)
 {
        struct sock *sk = sock->sk;
        struct tipc_port *tport = tipc_sk_port(sk);
@@ -1746,6 +1750,12 @@ static int getsockopt(struct socket *sock,
                value = jiffies_to_msecs(sk->sk_rcvtimeo);
                /* no need to set "res", since already 0 at this point */
                break;
+        case TIPC_NODE_RECVQ_DEPTH:
+               value = (u32)atomic_read(&tipc_queue_size);
+               break;
+        case TIPC_SOCK_RECVQ_DEPTH:
+               value = skb_queue_len(&sk->sk_receive_queue);
+               break;
        default:
                res = -EINVAL;
        }