commit eabcab2b7caab75ba8607c7dac225e4533998e80 Author: Nick Mathewson nickm@torproject.org Date: Wed Nov 20 11:56:35 2013 -0500
Count freed buffer bytes from buffers when oom-killing circuits.
Also, aggressively clear the buffers to try to make their bytes go away fast rather than waiting for the close-marked-connection code to get 'em. --- src/or/buffers.c | 2 +- src/or/circuitlist.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/src/or/buffers.c b/src/or/buffers.c index 4b176a8..71b61b1 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -547,7 +547,7 @@ buf_allocation(const buf_t *buf) size_t total = 0; const chunk_t *chunk; for (chunk = buf->head; chunk; chunk = chunk->next) { - total += chunk->memlen; + total += CHUNK_ALLOC_SIZE(chunk->memlen); } return total; } diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 27fe5ab..c7dfe36 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1373,6 +1373,36 @@ marked_circuit_free_cells(circuit_t *circ) cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_conn_cells); }
+/** DOCDOC */ +static size_t +marked_circuit_streams_free_bytes(edge_connection_t *stream) +{ + size_t result = 0; + for ( ; stream; stream = stream->next_stream) { + connection_t *conn = TO_CONN(stream); + if (conn->inbuf) { + result += buf_allocation(conn->inbuf); + buf_clear(conn->inbuf); + } + if (conn->outbuf) { + result += buf_allocation(conn->outbuf); + buf_clear(conn->outbuf); + } + } + return result; +} + +/** DOCDOC */ +static size_t +marked_circuit_free_stream_bytes(circuit_t *c) +{ + if (CIRCUIT_IS_ORIGIN(c)) { + return marked_circuit_streams_free_bytes(TO_ORIGIN_CIRCUIT(c)->p_streams); + } else { + return marked_circuit_streams_free_bytes(TO_OR_CIRCUIT(c)->n_streams); + } +} + /** Return the number of cells used by the circuit <b>c</b>'s cell queues. */ static size_t n_cells_in_circ_queues(const circuit_t *c) @@ -1486,7 +1516,8 @@ circuits_handle_oom(size_t current_allocation) /* Let's hope there's enough slack space for this allocation here... */ smartlist_t *circlist = smartlist_new(); circuit_t *circ; - size_t n_cells_removed=0, n_cells_to_remove; + size_t mem_to_recover; + size_t mem_recovered=0; int n_circuits_killed=0; struct timeval now; uint32_t now_ms; @@ -1497,11 +1528,9 @@ circuits_handle_oom(size_t current_allocation) { size_t mem_target = (size_t)(get_options()->MaxMemInCellQueues * FRACTION_OF_CELLS_TO_RETAIN_ON_OOM); - size_t mem_to_recover; if (current_allocation <= mem_target) return; mem_to_recover = current_allocation - mem_target; - n_cells_to_remove = CEIL_DIV(mem_to_recover, packed_cell_mem_cost()); }
tor_gettimeofday_cached(&now); @@ -1522,21 +1551,26 @@ circuits_handle_oom(size_t current_allocation) * them, and reclaim their storage aggressively. */ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { size_t n = n_cells_in_circ_queues(circ); + size_t freed; if (! circ->marked_for_close) { circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); } marked_circuit_free_cells(circ); + freed = marked_circuit_free_stream_bytes(circ);
++n_circuits_killed; - n_cells_removed += n; - if (n_cells_removed >= n_cells_to_remove) + + mem_recovered += n * packed_cell_mem_cost(); + mem_recovered += freed; + + if (mem_recovered >= mem_to_recover) break; } SMARTLIST_FOREACH_END(circ);
clean_cell_pool(); /* In case this helps. */
log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits.", - U64_PRINTF_ARG(n_cells_removed * packed_cell_mem_cost()), + U64_PRINTF_ARG(mem_recovered), n_circuits_killed);
smartlist_free(circlist);