]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/ipv4/tcp.c
tcp: add TCPMemoryPressuresChrono counter
[karo-tx-linux.git] / net / ipv4 / tcp.c
index 59792d283ff8c19048904cb790dbeebef14da73d..cc8fd8b747a47e9b66492ecdf27256ef6d879877 100644 (file)
@@ -320,17 +320,36 @@ struct tcp_splice_state {
  * All the __sk_mem_schedule() is of this nature: accounting
  * is strict, actions are advisory and have some latency.
  */
-int tcp_memory_pressure __read_mostly;
-EXPORT_SYMBOL(tcp_memory_pressure);
+unsigned long tcp_memory_pressure __read_mostly;
+EXPORT_SYMBOL_GPL(tcp_memory_pressure);
 
 void tcp_enter_memory_pressure(struct sock *sk)
 {
-       if (!tcp_memory_pressure) {
+       unsigned long val;
+
+       if (tcp_memory_pressure)
+               return;
+       val = jiffies;
+
+       if (!val)
+               val--;
+       if (!cmpxchg(&tcp_memory_pressure, 0, val))
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURES);
-               tcp_memory_pressure = 1;
-       }
 }
-EXPORT_SYMBOL(tcp_enter_memory_pressure);
+EXPORT_SYMBOL_GPL(tcp_enter_memory_pressure);
+
+void tcp_leave_memory_pressure(struct sock *sk)
+{
+       unsigned long val;
+
+       if (!tcp_memory_pressure)
+               return;
+       val = xchg(&tcp_memory_pressure, 0);
+       if (val)
+               NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURESCHRONO,
+                             jiffies_to_msecs(jiffies - val));
+}
+EXPORT_SYMBOL_GPL(tcp_leave_memory_pressure);
 
 /* Convert seconds to retransmits based on initial and max timeout */
 static u8 secs_to_retrans(int seconds, int timeout, int rto_max)
@@ -386,7 +405,7 @@ void tcp_init_sock(struct sock *sk)
 
        icsk->icsk_rto = TCP_TIMEOUT_INIT;
        tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
-       minmax_reset(&tp->rtt_min, tcp_time_stamp, ~0U);
+       minmax_reset(&tp->rtt_min, tcp_jiffies32, ~0U);
 
        /* So many TCP implementations out there (incorrectly) count the
         * initial SYN frame in their delayed-ACK and congestion control
@@ -2186,7 +2205,7 @@ adjudge_to_death:
 
 
        /* Now socket is owned by kernel and we acquire BH lock
-          to finish close. No need to check for user refs.
+        *  to finish close. No need to check for user refs.
         */
        local_bh_disable();
        bh_lock_sock(sk);
@@ -2381,9 +2400,10 @@ static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int l
        return 0;
 }
 
-static int tcp_repair_options_est(struct tcp_sock *tp,
+static int tcp_repair_options_est(struct sock *sk,
                struct tcp_repair_opt __user *optbuf, unsigned int len)
 {
+       struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_repair_opt opt;
 
        while (len >= sizeof(opt)) {
@@ -2396,6 +2416,7 @@ static int tcp_repair_options_est(struct tcp_sock *tp,
                switch (opt.opt_code) {
                case TCPOPT_MSS:
                        tp->rx_opt.mss_clamp = opt.opt_val;
+                       tcp_mtup_init(sk);
                        break;
                case TCPOPT_WINDOW:
                        {
@@ -2478,7 +2499,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
        case TCP_MAXSEG:
                /* Values greater than interface MTU won't take effect. However
                 * at the point when this call is done we typically don't yet
-                * know which interface is going to be used */
+                * know which interface is going to be used
+                */
                if (val && (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW)) {
                        err = -EINVAL;
                        break;
@@ -2555,7 +2577,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                if (!tp->repair)
                        err = -EINVAL;
                else if (sk->sk_state == TCP_ESTABLISHED)
-                       err = tcp_repair_options_est(tp,
+                       err = tcp_repair_options_est(sk,
                                        (struct tcp_repair_opt __user *)optval,
                                        optlen);
                else
@@ -2713,7 +2735,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                if (!tp->repair)
                        err = -EPERM;
                else
-                       tp->tsoffset = val - tcp_time_stamp;
+                       tp->tsoffset = val - tcp_time_stamp_raw();
                break;
        case TCP_REPAIR_WINDOW:
                err = tcp_repair_set_window(tp, optval, optlen);
@@ -2764,7 +2786,7 @@ static void tcp_get_info_chrono_stats(const struct tcp_sock *tp,
        for (i = TCP_CHRONO_BUSY; i < __TCP_CHRONO_MAX; ++i) {
                stats[i] = tp->chrono_stat[i - 1];
                if (i == tp->chrono_type)
-                       stats[i] += tcp_time_stamp - tp->chrono_start;
+                       stats[i] += tcp_jiffies32 - tp->chrono_start;
                stats[i] *= USEC_PER_SEC / HZ;
                total += stats[i];
        }
@@ -2848,7 +2870,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        info->tcpi_retrans = tp->retrans_out;
        info->tcpi_fackets = tp->fackets_out;
 
-       now = tcp_time_stamp;
+       now = tcp_jiffies32;
        info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
        info->tcpi_last_data_recv = jiffies_to_msecs(now - icsk->icsk_ack.lrcvtime);
        info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
@@ -3079,7 +3101,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
                break;
 
        case TCP_TIMESTAMP:
-               val = tcp_time_stamp + tp->tsoffset;
+               val = tcp_time_stamp_raw() + tp->tsoffset;
                break;
        case TCP_NOTSENT_LOWAT:
                val = tp->notsent_lowat;