powerpc/mm/book3s/64: Add proper pte access check helper
[linux-2.6-block.git] / net / rxrpc / conn_client.c
index 5f9624bd311c6882bc6f751b393b4904222f5667..7f74ca3059f8f45a70dd1960335415eee343b003 100644 (file)
@@ -85,8 +85,8 @@
 
 __read_mostly unsigned int rxrpc_max_client_connections = 1000;
 __read_mostly unsigned int rxrpc_reap_client_connections = 900;
-__read_mostly unsigned int rxrpc_conn_idle_client_expiry = 2 * 60 * HZ;
-__read_mostly unsigned int rxrpc_conn_idle_client_fast_expiry = 2 * HZ;
+__read_mostly unsigned long rxrpc_conn_idle_client_expiry = 2 * 60 * HZ;
+__read_mostly unsigned long rxrpc_conn_idle_client_fast_expiry = 2 * HZ;
 
 /*
  * We use machine-unique IDs for our client connections.
@@ -554,6 +554,11 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
 
        trace_rxrpc_client(conn, channel, rxrpc_client_chan_activate);
 
+       /* Cancel the final ACK on the previous call if it hasn't been sent yet
+        * as the DATA packet will implicitly ACK it.
+        */
+       clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
+
        write_lock_bh(&call->state_lock);
        if (!test_bit(RXRPC_CALL_TX_LASTQ, &call->flags))
                call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
@@ -686,7 +691,7 @@ int rxrpc_connect_call(struct rxrpc_call *call,
 
        _enter("{%d,%lx},", call->debug_id, call->user_call_ID);
 
-       rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper.work);
+       rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper);
        rxrpc_cull_active_client_conns(rxnet);
 
        ret = rxrpc_get_client_conn(call, cp, srx, gfp);
@@ -751,6 +756,18 @@ void rxrpc_expose_client_call(struct rxrpc_call *call)
        }
 }
 
+/*
+ * Set the reap timer.
+ */
+static void rxrpc_set_client_reap_timer(struct rxrpc_net *rxnet)
+{
+       unsigned long now = jiffies;
+       unsigned long reap_at = now + rxrpc_conn_idle_client_expiry;
+
+       if (rxnet->live)
+               timer_reduce(&rxnet->client_conn_reap_timer, reap_at);
+}
+
 /*
  * Disconnect a client call.
  */
@@ -813,6 +830,19 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
                goto out_2;
        }
 
+       /* Schedule the final ACK to be transmitted in a short while so that it
+        * can be skipped if we find a follow-on call.  The first DATA packet
+        * of the follow on call will implicitly ACK this call.
+        */
+       if (test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
+               unsigned long final_ack_at = jiffies + 2;
+
+               WRITE_ONCE(chan->final_ack_at, final_ack_at);
+               smp_wmb(); /* vs rxrpc_process_delayed_final_acks() */
+               set_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
+               rxrpc_reduce_conn_timer(conn, final_ack_at);
+       }
+
        /* Things are more complex and we need the cache lock.  We might be
         * able to simply idle the conn or it might now be lurking on the wait
         * list.  It might even get moved back to the active list whilst we're
@@ -878,9 +908,7 @@ idle_connection:
                list_move_tail(&conn->cache_link, &rxnet->idle_client_conns);
                if (rxnet->idle_client_conns.next == &conn->cache_link &&
                    !rxnet->kill_all_client_conns)
-                       queue_delayed_work(rxrpc_workqueue,
-                                          &rxnet->client_conn_reaper,
-                                          rxrpc_conn_idle_client_expiry);
+                       rxrpc_set_client_reap_timer(rxnet);
        } else {
                trace_rxrpc_client(conn, channel, rxrpc_client_to_inactive);
                conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
@@ -1018,8 +1046,7 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
 {
        struct rxrpc_connection *conn;
        struct rxrpc_net *rxnet =
-               container_of(to_delayed_work(work),
-                            struct rxrpc_net, client_conn_reaper);
+               container_of(work, struct rxrpc_net, client_conn_reaper);
        unsigned long expiry, conn_expires_at, now;
        unsigned int nr_conns;
        bool did_discard = false;
@@ -1061,6 +1088,8 @@ next:
                expiry = rxrpc_conn_idle_client_expiry;
                if (nr_conns > rxrpc_reap_client_connections)
                        expiry = rxrpc_conn_idle_client_fast_expiry;
+               if (conn->params.local->service_closed)
+                       expiry = rxrpc_closed_conn_expiry * HZ;
 
                conn_expires_at = conn->idle_timestamp + expiry;
 
@@ -1096,9 +1125,8 @@ not_yet_expired:
         */
        _debug("not yet");
        if (!rxnet->kill_all_client_conns)
-               queue_delayed_work(rxrpc_workqueue,
-                                  &rxnet->client_conn_reaper,
-                                  conn_expires_at - now);
+               timer_reduce(&rxnet->client_conn_reap_timer,
+                            conn_expires_at);
 
 out:
        spin_unlock(&rxnet->client_conn_cache_lock);
@@ -1118,9 +1146,9 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
        rxnet->kill_all_client_conns = true;
        spin_unlock(&rxnet->client_conn_cache_lock);
 
-       cancel_delayed_work(&rxnet->client_conn_reaper);
+       del_timer_sync(&rxnet->client_conn_reap_timer);
 
-       if (!queue_delayed_work(rxrpc_workqueue, &rxnet->client_conn_reaper, 0))
+       if (!rxrpc_queue_work(&rxnet->client_conn_reaper))
                _debug("destroy: queue failed");
 
        _leave("");