patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / net / ipv4 / tcp.c
index f5d991b..260cb40 100644 (file)
@@ -276,6 +276,8 @@ kmem_cache_t *tcp_timewait_cachep;
 
 atomic_t tcp_orphan_count = ATOMIC_INIT(0);
 
+int sysctl_tcp_default_win_scale;
+
 int sysctl_tcp_mem[3];
 int sysctl_tcp_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
 int sysctl_tcp_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
@@ -528,7 +530,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                return -ENOIOCTLCMD;
        };
 
-       return put_user(answ, (int *)arg);
+       return put_user(answ, (int __user *)arg);
 }
 
 
@@ -646,7 +648,7 @@ static void tcp_listen_stop (struct sock *sk)
                local_bh_enable();
                sock_put(child);
 
-               tcp_acceptq_removed(sk);
+               sk_acceptq_removed(sk);
                tcp_openreq_fastfree(req);
        }
        BUG_TRAP(!sk->sk_ack_backlog);
@@ -964,7 +966,7 @@ ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset,
 #define TCP_PAGE(sk)   (inet_sk(sk)->sndmsg_page)
 #define TCP_OFF(sk)    (inet_sk(sk)->sndmsg_off)
 
-static inline int tcp_copy_to_page(struct sock *sk, char *from,
+static inline int tcp_copy_to_page(struct sock *sk, char __user *from,
                                   struct sk_buff *skb, struct page *page,
                                   int off, int copy)
 {
@@ -989,7 +991,7 @@ static inline int tcp_copy_to_page(struct sock *sk, char *from,
        return 0;
 }
 
-static inline int skb_add_data(struct sk_buff *skb, char *from, int copy)
+static inline int skb_add_data(struct sk_buff *skb, char __user *from, int copy)
 {
        int err = 0;
        unsigned int csum;
@@ -1063,7 +1065,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        while (--iovlen >= 0) {
                int seglen = iov->iov_len;
-               unsigned char *from = iov->iov_base;
+               unsigned char __user *from = iov->iov_base;
 
                iov++;
 
@@ -1294,18 +1296,6 @@ static int tcp_recv_urg(struct sock *sk, long timeo,
        return -EAGAIN;
 }
 
-/*
- *     Release a skb if it is no longer needed. This routine
- *     must be called with interrupts disabled or with the
- *     socket locked so that the sk_buff queue operation is ok.
- */
-
-static inline void tcp_eat_skb(struct sock *sk, struct sk_buff *skb)
-{
-       __skb_unlink(skb, &sk->sk_receive_queue);
-       __kfree_skb(skb);
-}
-
 /* Clean up the receive buffer for full frames taken by the user,
  * then send an ACK if necessary.  COPIED is the number of bytes
  * tcp_recvmsg has given to the user so far, it speeds up the
@@ -1366,31 +1356,6 @@ static void cleanup_rbuf(struct sock *sk, int copied)
                tcp_send_ack(sk);
 }
 
-/* Now socket state including sk->sk_err is changed only under lock,
- * hence we may omit checks after joining wait queue.
- * We check receive queue before schedule() only as optimization;
- * it is very likely that release_sock() added new data.
- */
-
-static long tcp_data_wait(struct sock *sk, long timeo)
-{
-       DEFINE_WAIT(wait);
-
-       prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
-
-       set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-       release_sock(sk);
-
-       if (skb_queue_empty(&sk->sk_receive_queue))
-               timeo = schedule_timeout(timeo);
-
-       lock_sock(sk);
-       clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-
-       finish_wait(sk->sk_sleep, &wait);
-       return timeo;
-}
-
 static void tcp_prequeue_process(struct sock *sk)
 {
        struct sk_buff *skb;
@@ -1471,15 +1436,18 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
                                break;
                }
                if (skb->h.th->fin) {
-                       tcp_eat_skb(sk, skb);
+                       sk_eat_skb(sk, skb);
                        ++seq;
                        break;
                }
-               tcp_eat_skb(sk, skb);
+               sk_eat_skb(sk, skb);
                if (!desc->count)
                        break;
        }
        tp->copied_seq = seq;
+
+       tcp_rcv_space_adjust(sk);
+
        /* Clean up data we have read: This will do ACK frames. */
        if (copied)
                cleanup_rbuf(sk, copied);
@@ -1667,9 +1635,8 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        /* Do not sleep, just process backlog. */
                        release_sock(sk);
                        lock_sock(sk);
-               } else {
-                       timeo = tcp_data_wait(sk, timeo);
-               }
+               } else
+                       sk_wait_data(sk, &timeo);
 
                if (user_recv) {
                        int chunk;
@@ -1740,6 +1707,8 @@ do_prequeue:
                copied += used;
                len -= used;
 
+               tcp_rcv_space_adjust(sk);
+
 skip_copy:
                if (tp->urg_data && after(tp->copied_seq, tp->urg_seq)) {
                        tp->urg_data = 0;
@@ -1751,14 +1720,14 @@ skip_copy:
                if (skb->h.th->fin)
                        goto found_fin_ok;
                if (!(flags & MSG_PEEK))
-                       tcp_eat_skb(sk, skb);
+                       sk_eat_skb(sk, skb);
                continue;
 
        found_fin_ok:
                /* Process the FIN. */
                ++*seq;
                if (!(flags & MSG_PEEK))
-                       tcp_eat_skb(sk, skb);
+                       sk_eat_skb(sk, skb);
                break;
        } while (len > 0);
 
@@ -2256,7 +2225,7 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err)
                tp->accept_queue_tail = NULL;
 
        newsk = req->sk;
-       tcp_acceptq_removed(sk);
+       sk_acceptq_removed(sk);
        tcp_openreq_fastfree(req);
        BUG_TRAP(newsk->sk_state != TCP_SYN_RECV);
        release_sock(sk);
@@ -2271,7 +2240,7 @@ out:
 /*
  *     Socket option code for TCP.
  */
-int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
+int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
                   int optlen)
 {
        struct tcp_opt *tp = tcp_sk(sk);
@@ -2285,7 +2254,7 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
        if (optlen < sizeof(int))
                return -EINVAL;
 
-       if (get_user(val, (int *)optval))
+       if (get_user(val, (int __user *)optval))
                return -EFAULT;
 
        lock_sock(sk);
@@ -2435,8 +2404,8 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
        return err;
 }
 
-int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
-                  int *optlen)
+int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
+                  int __user *optlen)
 {
        struct tcp_opt *tp = tcp_sk(sk);
        int val, len;
@@ -2491,56 +2460,11 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
                break;
        case TCP_INFO: {
                struct tcp_info info;
-               u32 now = tcp_time_stamp;
 
                if (get_user(len, optlen))
                        return -EFAULT;
-               info.tcpi_state = sk->sk_state;
-               info.tcpi_ca_state = tp->ca_state;
-               info.tcpi_retransmits = tp->retransmits;
-               info.tcpi_probes = tp->probes_out;
-               info.tcpi_backoff = tp->backoff;
-               info.tcpi_options = 0;
-               if (tp->tstamp_ok)
-                       info.tcpi_options |= TCPI_OPT_TIMESTAMPS;
-               if (tp->sack_ok)
-                       info.tcpi_options |= TCPI_OPT_SACK;
-               if (tp->wscale_ok) {
-                       info.tcpi_options |= TCPI_OPT_WSCALE;
-                       info.tcpi_snd_wscale = tp->snd_wscale;
-                       info.tcpi_rcv_wscale = tp->rcv_wscale;
-               } else {
-                       info.tcpi_snd_wscale = 0;
-                       info.tcpi_rcv_wscale = 0;
-               }
-               if (tp->ecn_flags & TCP_ECN_OK)
-                       info.tcpi_options |= TCPI_OPT_ECN;
-
-               info.tcpi_rto = (1000000 * tp->rto) / HZ;
-               info.tcpi_ato = (1000000 * tp->ack.ato) / HZ;
-               info.tcpi_snd_mss = tp->mss_cache_std;
-               info.tcpi_rcv_mss = tp->ack.rcv_mss;
-
-               info.tcpi_unacked = tp->packets_out;
-               info.tcpi_sacked = tp->sacked_out;
-               info.tcpi_lost = tp->lost_out;
-               info.tcpi_retrans = tp->retrans_out;
-               info.tcpi_fackets = tp->fackets_out;
-
-               info.tcpi_last_data_sent = ((now - tp->lsndtime) * 1000) / HZ;
-               info.tcpi_last_ack_sent = 0;
-               info.tcpi_last_data_recv = ((now -
-                                            tp->ack.lrcvtime) * 1000) / HZ;
-               info.tcpi_last_ack_recv = ((now - tp->rcv_tstamp) * 1000) / HZ;
-
-               info.tcpi_pmtu = tp->pmtu_cookie;
-               info.tcpi_rcv_ssthresh = tp->rcv_ssthresh;
-               info.tcpi_rtt = ((1000000 * tp->srtt) / HZ) >> 3;
-               info.tcpi_rttvar = ((1000000 * tp->mdev) / HZ) >> 2;
-               info.tcpi_snd_ssthresh = tp->snd_ssthresh;
-               info.tcpi_snd_cwnd = tp->snd_cwnd;
-               info.tcpi_advmss = tp->advmss;
-               info.tcpi_reordering = tp->reordering;
+
+               tcp_get_info(sk, &info);
 
                len = min_t(unsigned int, len, sizeof(info));
                if (put_user(len, optlen))
@@ -2675,10 +2599,6 @@ void __init tcp_init(void)
        sysctl_tcp_mem[0] =  768 << order;
        sysctl_tcp_mem[1] = 1024 << order;
        sysctl_tcp_mem[2] = 1536 << order;
-       if (sysctl_tcp_mem[2] - sysctl_tcp_mem[1] > 512)
-               sysctl_tcp_mem[1] = sysctl_tcp_mem[2] - 512;
-       if (sysctl_tcp_mem[1] - sysctl_tcp_mem[0] > 512)
-               sysctl_tcp_mem[0] = sysctl_tcp_mem[1] - 512;
 
        if (order < 3) {
                sysctl_tcp_wmem[2] = 64 * 1024;