]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/tipc/socket.c
[TIPC]: Allow stream receive to read from multiple TIPC messages
[mv-sheeva.git] / net / tipc / socket.c
index 9ae8e9f74028f23b86841b57e16318d445b84e07..c1a199c0fa6d838119bf1cca89df479e75d692eb 100644 (file)
@@ -58,7 +58,8 @@
 #define SS_LISTENING   -1      /* socket is listening */
 #define SS_READY       -2      /* socket is connectionless */
 
-#define OVERLOAD_LIMIT_BASE    5000
+#define OVERLOAD_LIMIT_BASE    5000
+#define CONN_TIMEOUT_DEFAULT   8000    /* default connect timeout = 8s */
 
 struct tipc_sock {
        struct sock sk;
@@ -101,44 +102,6 @@ static void sock_unlock(struct tipc_sock* tsock)
        spin_unlock_bh(tsock->p->lock);
 }
 
-/**
- * pollmask - determine the current set of poll() events for a socket
- * @sock: socket structure
- *
- * TIPC sets the returned events as follows:
- * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
- *    or if a connection-oriented socket is does not have an active connection
- *    (i.e. a read operation will not block).
- * b) POLLOUT is set except when a socket's connection has been terminated
- *    (i.e. a write operation will not block).
- * c) POLLHUP is set when a socket's connection has been terminated.
- *
- * IMPORTANT: The fact that a read or write operation will not block does NOT
- * imply that the operation will succeed!
- *
- * Returns pollmask value
- */
-
-static u32 pollmask(struct socket *sock)
-{
-       u32 mask;
-
-       if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) ||
-           (sock->state == SS_UNCONNECTED) ||
-           (sock->state == SS_DISCONNECTING))
-               mask = (POLLRDNORM | POLLIN);
-       else
-               mask = 0;
-
-       if (sock->state == SS_DISCONNECTING)
-               mask |= POLLHUP;
-       else
-               mask |= POLLOUT;
-
-       return mask;
-}
-
-
 /**
  * advance_queue - discard first buffer in queue
  * @tsock: TIPC socket
@@ -208,8 +171,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
        }
 
        sock_init_data(sock, sk);
-       init_waitqueue_head(sk->sk_sleep);
-       sk->sk_rcvtimeo = 8 * HZ;   /* default connect timeout = 8s */
+       sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
 
        tsock = tipc_sk(sk);
        port = tipc_get_port(ref);
@@ -390,15 +352,47 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
  * @sock: socket for which to calculate the poll bits
  * @wait: ???
  *
- * Returns the pollmask
+ * Returns pollmask value
+ *
+ * COMMENTARY:
+ * It appears that the usual socket locking mechanisms are not useful here
+ * since the pollmask info is potentially out-of-date the moment this routine
+ * exits.  TCP and other protocols seem to rely on higher level poll routines
+ * to handle any preventable race conditions, so TIPC will do the same ...
+ *
+ * TIPC sets the returned events as follows:
+ * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
+ *    or if a connection-oriented socket is does not have an active connection
+ *    (i.e. a read operation will not block).
+ * b) POLLOUT is set except when a socket's connection has been terminated
+ *    (i.e. a write operation will not block).
+ * c) POLLHUP is set when a socket's connection has been terminated.
+ *
+ * IMPORTANT: The fact that a read or write operation will not block does NOT
+ * imply that the operation will succeed!
  */
 
 static unsigned int poll(struct file *file, struct socket *sock,
                         poll_table *wait)
 {
-       poll_wait(file, sock->sk->sk_sleep, wait);
-       /* NEED LOCK HERE? */
-       return pollmask(sock);
+       struct sock *sk = sock->sk;
+       u32 mask;
+
+       poll_wait(file, sk->sk_sleep, wait);
+
+       if (!skb_queue_empty(&sk->sk_receive_queue) ||
+           (sock->state == SS_UNCONNECTED) ||
+           (sock->state == SS_DISCONNECTING))
+               mask = (POLLRDNORM | POLLIN);
+       else
+               mask = 0;
+
+       if (sock->state == SS_DISCONNECTING)
+               mask |= POLLHUP;
+       else
+               mask |= POLLOUT;
+
+       return mask;
 }
 
 /**
@@ -925,7 +919,8 @@ restart:
        /* Consume received message (optional) */
 
        if (likely(!(flags & MSG_PEEK))) {
-               if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+               if ((sock->state != SS_READY) &&
+                   (++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
                        tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
                advance_queue(tsock);
        }
@@ -1070,7 +1065,9 @@ restart:
        /* Loop around if more data is required */
 
        if ((sz_copied < buf_len)    /* didn't get all requested data */
-           && (flags & MSG_WAITALL) /* ... and need to wait for more */
+           && (!skb_queue_empty(&sock->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 */
            )
@@ -1375,7 +1372,7 @@ static int accept(struct socket *sock, struct socket *newsock, int flags)
        }
        buf = skb_peek(&sock->sk->sk_receive_queue);
 
-       res = tipc_create(sock->sk->sk_net, newsock, 0);
+       res = tipc_create(sock_net(sock->sk), newsock, 0);
        if (!res) {
                struct tipc_sock *new_tsock = tipc_sk(newsock->sk);
                struct tipc_portid id;
@@ -1419,7 +1416,7 @@ exit:
 /**
  * shutdown - shutdown socket connection
  * @sock: socket structure
- * @how: direction to close (unused; always treated as read + write)
+ * @how: direction to close (must be SHUT_RDWR)
  *
  * Terminates connection (if necessary), then purges socket's receive queue.
  *
@@ -1432,7 +1429,8 @@ static int shutdown(struct socket *sock, int how)
        struct sk_buff *buf;
        int res;
 
-       /* Could return -EINVAL for an invalid "how", but why bother? */
+       if (how != SHUT_RDWR)
+               return -EINVAL;
 
        if (mutex_lock_interruptible(&tsock->lock))
                return -ERESTARTSYS;
@@ -1535,7 +1533,7 @@ static int setsockopt(struct socket *sock,
                res = tipc_set_portunreturnable(tsock->p->ref, value);
                break;
        case TIPC_CONN_TIMEOUT:
-               sock->sk->sk_rcvtimeo = (value * HZ / 1000);
+               sock->sk->sk_rcvtimeo = msecs_to_jiffies(value);
                break;
        default:
                res = -EINVAL;
@@ -1588,7 +1586,7 @@ static int getsockopt(struct socket *sock,
                res = tipc_portunreturnable(tsock->p->ref, &value);
                break;
        case TIPC_CONN_TIMEOUT:
-               value = (sock->sk->sk_rcvtimeo * 1000) / HZ;
+               value = jiffies_to_msecs(sock->sk->sk_rcvtimeo);
                break;
        default:
                res = -EINVAL;