aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-08-23 10:27:24 -0400
committerDavid Howells <dhowells@redhat.com>2016-08-23 11:02:35 -0400
commitf51b4480021c470d1f5e8066ccc7c10513bd4e37 (patch)
tree63b43923ac921fe8e3509d5b06f0efafe062a038
parentdf844fd46b98c2efde8f4ac2d50d59bc90c4c679 (diff)
rxrpc: Set connection expiry on idle, not put
Set the connection expiry time when a connection becomes idle rather than doing this in rxrpc_put_connection(). This makes the put path more efficient (it is likely to be called occasionally whilst a connection has outstanding calls because active workqueue items needs to be given a ref). The time is also preset in the connection allocator in case the connection never gets used. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--net/rxrpc/ar-internal.h11
-rw-r--r--net/rxrpc/conn_object.c42
2 files changed, 26 insertions, 27 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 8cb517fbbd23..66c917077880 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -313,7 +313,7 @@ struct rxrpc_connection {
313 struct rxrpc_crypt csum_iv; /* packet checksum base */ 313 struct rxrpc_crypt csum_iv; /* packet checksum base */
314 unsigned long flags; 314 unsigned long flags;
315 unsigned long events; 315 unsigned long events;
316 unsigned long put_time; /* Time at which last put */ 316 unsigned long idle_timestamp; /* Time at which last became idle */
317 spinlock_t state_lock; /* state-change lock */ 317 spinlock_t state_lock; /* state-change lock */
318 atomic_t usage; 318 atomic_t usage;
319 enum rxrpc_conn_proto_state state : 8; /* current state of connection */ 319 enum rxrpc_conn_proto_state state : 8; /* current state of connection */
@@ -565,7 +565,7 @@ struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *,
565 struct sk_buff *); 565 struct sk_buff *);
566void __rxrpc_disconnect_call(struct rxrpc_call *); 566void __rxrpc_disconnect_call(struct rxrpc_call *);
567void rxrpc_disconnect_call(struct rxrpc_call *); 567void rxrpc_disconnect_call(struct rxrpc_call *);
568void rxrpc_put_connection(struct rxrpc_connection *); 568void __rxrpc_put_connection(struct rxrpc_connection *);
569void __exit rxrpc_destroy_all_connections(void); 569void __exit rxrpc_destroy_all_connections(void);
570 570
571static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn) 571static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn)
@@ -589,6 +589,13 @@ struct rxrpc_connection *rxrpc_get_connection_maybe(struct rxrpc_connection *con
589 return atomic_inc_not_zero(&conn->usage) ? conn : NULL; 589 return atomic_inc_not_zero(&conn->usage) ? conn : NULL;
590} 590}
591 591
592static inline void rxrpc_put_connection(struct rxrpc_connection *conn)
593{
594 if (conn && atomic_dec_return(&conn->usage) == 1)
595 __rxrpc_put_connection(conn);
596}
597
598
592static inline bool rxrpc_queue_conn(struct rxrpc_connection *conn) 599static inline bool rxrpc_queue_conn(struct rxrpc_connection *conn)
593{ 600{
594 if (!rxrpc_get_connection_maybe(conn)) 601 if (!rxrpc_get_connection_maybe(conn))
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 6a5a17efc538..743f0bb4aaa8 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -56,6 +56,7 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
56 atomic_set(&conn->avail_chans, RXRPC_MAXCALLS); 56 atomic_set(&conn->avail_chans, RXRPC_MAXCALLS);
57 conn->size_align = 4; 57 conn->size_align = 4;
58 conn->header_size = sizeof(struct rxrpc_wire_header); 58 conn->header_size = sizeof(struct rxrpc_wire_header);
59 conn->idle_timestamp = jiffies;
59 } 60 }
60 61
61 _leave(" = %p{%d}", conn, conn ? conn->debug_id : 0); 62 _leave(" = %p{%d}", conn, conn ? conn->debug_id : 0);
@@ -191,29 +192,16 @@ void rxrpc_disconnect_call(struct rxrpc_call *call)
191 spin_unlock(&conn->channel_lock); 192 spin_unlock(&conn->channel_lock);
192 193
193 call->conn = NULL; 194 call->conn = NULL;
195 conn->idle_timestamp = jiffies;
194 rxrpc_put_connection(conn); 196 rxrpc_put_connection(conn);
195} 197}
196 198
197/* 199/*
198 * release a virtual connection 200 * release a virtual connection
199 */ 201 */
200void rxrpc_put_connection(struct rxrpc_connection *conn) 202void __rxrpc_put_connection(struct rxrpc_connection *conn)
201{ 203{
202 if (!conn) 204 rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0);
203 return;
204
205 _enter("%p{u=%d,d=%d}",
206 conn, atomic_read(&conn->usage), conn->debug_id);
207
208 ASSERTCMP(atomic_read(&conn->usage), >, 1);
209
210 conn->put_time = ktime_get_seconds();
211 if (atomic_dec_return(&conn->usage) == 1) {
212 _debug("zombie");
213 rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0);
214 }
215
216 _leave("");
217} 205}
218 206
219/* 207/*
@@ -248,14 +236,14 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu)
248static void rxrpc_connection_reaper(struct work_struct *work) 236static void rxrpc_connection_reaper(struct work_struct *work)
249{ 237{
250 struct rxrpc_connection *conn, *_p; 238 struct rxrpc_connection *conn, *_p;
251 unsigned long reap_older_than, earliest, put_time, now; 239 unsigned long reap_older_than, earliest, idle_timestamp, now;
252 240
253 LIST_HEAD(graveyard); 241 LIST_HEAD(graveyard);
254 242
255 _enter(""); 243 _enter("");
256 244
257 now = ktime_get_seconds(); 245 now = jiffies;
258 reap_older_than = now - rxrpc_connection_expiry; 246 reap_older_than = now - rxrpc_connection_expiry * HZ;
259 earliest = ULONG_MAX; 247 earliest = ULONG_MAX;
260 248
261 write_lock(&rxrpc_connection_lock); 249 write_lock(&rxrpc_connection_lock);
@@ -264,10 +252,14 @@ static void rxrpc_connection_reaper(struct work_struct *work)
264 if (likely(atomic_read(&conn->usage) > 1)) 252 if (likely(atomic_read(&conn->usage) > 1))
265 continue; 253 continue;
266 254
267 put_time = READ_ONCE(conn->put_time); 255 idle_timestamp = READ_ONCE(conn->idle_timestamp);
268 if (time_after(put_time, reap_older_than)) { 256 _debug("reap CONN %d { u=%d,t=%ld }",
269 if (time_before(put_time, earliest)) 257 conn->debug_id, atomic_read(&conn->usage),
270 earliest = put_time; 258 (long)reap_older_than - (long)idle_timestamp);
259
260 if (time_after(idle_timestamp, reap_older_than)) {
261 if (time_before(idle_timestamp, earliest))
262 earliest = idle_timestamp;
271 continue; 263 continue;
272 } 264 }
273 265
@@ -288,9 +280,9 @@ static void rxrpc_connection_reaper(struct work_struct *work)
288 280
289 if (earliest != ULONG_MAX) { 281 if (earliest != ULONG_MAX) {
290 _debug("reschedule reaper %ld", (long) earliest - now); 282 _debug("reschedule reaper %ld", (long) earliest - now);
291 ASSERTCMP(earliest, >, now); 283 ASSERT(time_after(earliest, now));
292 rxrpc_queue_delayed_work(&rxrpc_connection_reap, 284 rxrpc_queue_delayed_work(&rxrpc_connection_reap,
293 (earliest - now) * HZ); 285 earliest - now);
294 } 286 }
295 287
296 while (!list_empty(&graveyard)) { 288 while (!list_empty(&graveyard)) {