diff options
author | Lai Jiangshan <laijs@cn.fujitsu.com> | 2009-04-23 23:27:05 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-04-24 00:08:38 -0400 |
commit | 334d4169a6592d3fcd863bbe822a8f6985ffa9af (patch) | |
tree | 3ac9c038304eaa69b06d9cac735fd62a8d6c47b3 | |
parent | c2518c4366f087ebc10b3919cb2461bbe4f42d0c (diff) |
ring_buffer: compressed event header
RB_MAX_SMALL_DATA = 28bytes is too small for most tracers, it wastes
an 'u32' to save the actually length for events which data size > 28.
This fix uses compressed event header and enlarges RB_MAX_SMALL_DATA.
[ Impact: saves about 0%-12.5%(depends on tracer) memory in ring_buffer ]
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
LKML-Reference: <49F13189.3090000@cn.fujitsu.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | include/linux/ring_buffer.h | 16 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 83 |
2 files changed, 50 insertions, 49 deletions
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index fac8f1ac6f49..1c2f80911fbe 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h | |||
@@ -11,7 +11,7 @@ struct ring_buffer_iter; | |||
11 | * Don't refer to this struct directly, use functions below. | 11 | * Don't refer to this struct directly, use functions below. |
12 | */ | 12 | */ |
13 | struct ring_buffer_event { | 13 | struct ring_buffer_event { |
14 | u32 type:2, len:3, time_delta:27; | 14 | u32 type_len:5, time_delta:27; |
15 | u32 array[]; | 15 | u32 array[]; |
16 | }; | 16 | }; |
17 | 17 | ||
@@ -24,7 +24,8 @@ struct ring_buffer_event { | |||
24 | * size is variable depending on how much | 24 | * size is variable depending on how much |
25 | * padding is needed | 25 | * padding is needed |
26 | * If time_delta is non zero: | 26 | * If time_delta is non zero: |
27 | * everything else same as RINGBUF_TYPE_DATA | 27 | * array[0] holds the actual length |
28 | * size = 4 + length (bytes) | ||
28 | * | 29 | * |
29 | * @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta | 30 | * @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta |
30 | * array[0] = time delta (28 .. 59) | 31 | * array[0] = time delta (28 .. 59) |
@@ -35,22 +36,23 @@ struct ring_buffer_event { | |||
35 | * array[1..2] = tv_sec | 36 | * array[1..2] = tv_sec |
36 | * size = 16 bytes | 37 | * size = 16 bytes |
37 | * | 38 | * |
38 | * @RINGBUF_TYPE_DATA: Data record | 39 | * <= @RINGBUF_TYPE_DATA_TYPE_LEN_MAX: |
39 | * If len is zero: | 40 | * Data record |
41 | * If type_len is zero: | ||
40 | * array[0] holds the actual length | 42 | * array[0] holds the actual length |
41 | * array[1..(length+3)/4] holds data | 43 | * array[1..(length+3)/4] holds data |
42 | * size = 4 + 4 + length (bytes) | 44 | * size = 4 + length (bytes) |
43 | * else | 45 | * else |
44 | * length = len << 2 | 46 | * length = type_len << 2 |
45 | * array[0..(length+3)/4-1] holds data | 47 | * array[0..(length+3)/4-1] holds data |
46 | * size = 4 + length (bytes) | 48 | * size = 4 + length (bytes) |
47 | */ | 49 | */ |
48 | enum ring_buffer_type { | 50 | enum ring_buffer_type { |
51 | RINGBUF_TYPE_DATA_TYPE_LEN_MAX = 28, | ||
49 | RINGBUF_TYPE_PADDING, | 52 | RINGBUF_TYPE_PADDING, |
50 | RINGBUF_TYPE_TIME_EXTEND, | 53 | RINGBUF_TYPE_TIME_EXTEND, |
51 | /* FIXME: RINGBUF_TYPE_TIME_STAMP not implemented */ | 54 | /* FIXME: RINGBUF_TYPE_TIME_STAMP not implemented */ |
52 | RINGBUF_TYPE_TIME_STAMP, | 55 | RINGBUF_TYPE_TIME_STAMP, |
53 | RINGBUF_TYPE_DATA, | ||
54 | }; | 56 | }; |
55 | 57 | ||
56 | unsigned ring_buffer_event_length(struct ring_buffer_event *event); | 58 | unsigned ring_buffer_event_length(struct ring_buffer_event *event); |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 61dbdf21cd32..9692f100ec1a 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -28,8 +28,8 @@ int ring_buffer_print_entry_header(struct trace_seq *s) | |||
28 | { | 28 | { |
29 | int ret; | 29 | int ret; |
30 | 30 | ||
31 | ret = trace_seq_printf(s, "\ttype : 2 bits\n"); | 31 | ret = trace_seq_printf(s, "# compressed entry header\n"); |
32 | ret = trace_seq_printf(s, "\tlen : 3 bits\n"); | 32 | ret = trace_seq_printf(s, "\ttype_len : 5 bits\n"); |
33 | ret = trace_seq_printf(s, "\ttime_delta : 27 bits\n"); | 33 | ret = trace_seq_printf(s, "\ttime_delta : 27 bits\n"); |
34 | ret = trace_seq_printf(s, "\tarray : 32 bits\n"); | 34 | ret = trace_seq_printf(s, "\tarray : 32 bits\n"); |
35 | ret = trace_seq_printf(s, "\n"); | 35 | ret = trace_seq_printf(s, "\n"); |
@@ -37,8 +37,8 @@ int ring_buffer_print_entry_header(struct trace_seq *s) | |||
37 | RINGBUF_TYPE_PADDING); | 37 | RINGBUF_TYPE_PADDING); |
38 | ret = trace_seq_printf(s, "\ttime_extend : type == %d\n", | 38 | ret = trace_seq_printf(s, "\ttime_extend : type == %d\n", |
39 | RINGBUF_TYPE_TIME_EXTEND); | 39 | RINGBUF_TYPE_TIME_EXTEND); |
40 | ret = trace_seq_printf(s, "\tdata : type == %d\n", | 40 | ret = trace_seq_printf(s, "\tdata max type_len == %d\n", |
41 | RINGBUF_TYPE_DATA); | 41 | RINGBUF_TYPE_DATA_TYPE_LEN_MAX); |
42 | 42 | ||
43 | return ret; | 43 | return ret; |
44 | } | 44 | } |
@@ -204,7 +204,10 @@ EXPORT_SYMBOL_GPL(tracing_is_on); | |||
204 | 204 | ||
205 | #define RB_EVNT_HDR_SIZE (offsetof(struct ring_buffer_event, array)) | 205 | #define RB_EVNT_HDR_SIZE (offsetof(struct ring_buffer_event, array)) |
206 | #define RB_ALIGNMENT 4U | 206 | #define RB_ALIGNMENT 4U |
207 | #define RB_MAX_SMALL_DATA 28 | 207 | #define RB_MAX_SMALL_DATA (RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX) |
208 | |||
209 | /* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */ | ||
210 | #define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX | ||
208 | 211 | ||
209 | enum { | 212 | enum { |
210 | RB_LEN_TIME_EXTEND = 8, | 213 | RB_LEN_TIME_EXTEND = 8, |
@@ -213,17 +216,18 @@ enum { | |||
213 | 216 | ||
214 | static inline int rb_null_event(struct ring_buffer_event *event) | 217 | static inline int rb_null_event(struct ring_buffer_event *event) |
215 | { | 218 | { |
216 | return event->type == RINGBUF_TYPE_PADDING && event->time_delta == 0; | 219 | return event->type_len == RINGBUF_TYPE_PADDING |
220 | && event->time_delta == 0; | ||
217 | } | 221 | } |
218 | 222 | ||
219 | static inline int rb_discarded_event(struct ring_buffer_event *event) | 223 | static inline int rb_discarded_event(struct ring_buffer_event *event) |
220 | { | 224 | { |
221 | return event->type == RINGBUF_TYPE_PADDING && event->time_delta; | 225 | return event->type_len == RINGBUF_TYPE_PADDING && event->time_delta; |
222 | } | 226 | } |
223 | 227 | ||
224 | static void rb_event_set_padding(struct ring_buffer_event *event) | 228 | static void rb_event_set_padding(struct ring_buffer_event *event) |
225 | { | 229 | { |
226 | event->type = RINGBUF_TYPE_PADDING; | 230 | event->type_len = RINGBUF_TYPE_PADDING; |
227 | event->time_delta = 0; | 231 | event->time_delta = 0; |
228 | } | 232 | } |
229 | 233 | ||
@@ -232,8 +236,8 @@ rb_event_data_length(struct ring_buffer_event *event) | |||
232 | { | 236 | { |
233 | unsigned length; | 237 | unsigned length; |
234 | 238 | ||
235 | if (event->len) | 239 | if (event->type_len) |
236 | length = event->len * RB_ALIGNMENT; | 240 | length = event->type_len * RB_ALIGNMENT; |
237 | else | 241 | else |
238 | length = event->array[0]; | 242 | length = event->array[0]; |
239 | return length + RB_EVNT_HDR_SIZE; | 243 | return length + RB_EVNT_HDR_SIZE; |
@@ -243,12 +247,12 @@ rb_event_data_length(struct ring_buffer_event *event) | |||
243 | static unsigned | 247 | static unsigned |
244 | rb_event_length(struct ring_buffer_event *event) | 248 | rb_event_length(struct ring_buffer_event *event) |
245 | { | 249 | { |
246 | switch (event->type) { | 250 | switch (event->type_len) { |
247 | case RINGBUF_TYPE_PADDING: | 251 | case RINGBUF_TYPE_PADDING: |
248 | if (rb_null_event(event)) | 252 | if (rb_null_event(event)) |
249 | /* undefined */ | 253 | /* undefined */ |
250 | return -1; | 254 | return -1; |
251 | return rb_event_data_length(event); | 255 | return event->array[0] + RB_EVNT_HDR_SIZE; |
252 | 256 | ||
253 | case RINGBUF_TYPE_TIME_EXTEND: | 257 | case RINGBUF_TYPE_TIME_EXTEND: |
254 | return RB_LEN_TIME_EXTEND; | 258 | return RB_LEN_TIME_EXTEND; |
@@ -272,7 +276,7 @@ rb_event_length(struct ring_buffer_event *event) | |||
272 | unsigned ring_buffer_event_length(struct ring_buffer_event *event) | 276 | unsigned ring_buffer_event_length(struct ring_buffer_event *event) |
273 | { | 277 | { |
274 | unsigned length = rb_event_length(event); | 278 | unsigned length = rb_event_length(event); |
275 | if (event->type != RINGBUF_TYPE_DATA) | 279 | if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX) |
276 | return length; | 280 | return length; |
277 | length -= RB_EVNT_HDR_SIZE; | 281 | length -= RB_EVNT_HDR_SIZE; |
278 | if (length > RB_MAX_SMALL_DATA + sizeof(event->array[0])) | 282 | if (length > RB_MAX_SMALL_DATA + sizeof(event->array[0])) |
@@ -285,9 +289,9 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_length); | |||
285 | static void * | 289 | static void * |
286 | rb_event_data(struct ring_buffer_event *event) | 290 | rb_event_data(struct ring_buffer_event *event) |
287 | { | 291 | { |
288 | BUG_ON(event->type != RINGBUF_TYPE_DATA); | 292 | BUG_ON(event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX); |
289 | /* If length is in len field, then array[0] has the data */ | 293 | /* If length is in len field, then array[0] has the data */ |
290 | if (event->len) | 294 | if (event->type_len) |
291 | return (void *)&event->array[0]; | 295 | return (void *)&event->array[0]; |
292 | /* Otherwise length is in array[0] and array[1] has the data */ | 296 | /* Otherwise length is in array[0] and array[1] has the data */ |
293 | return (void *)&event->array[1]; | 297 | return (void *)&event->array[1]; |
@@ -988,7 +992,7 @@ static void rb_update_overflow(struct ring_buffer_per_cpu *cpu_buffer) | |||
988 | if (RB_WARN_ON(cpu_buffer, rb_null_event(event))) | 992 | if (RB_WARN_ON(cpu_buffer, rb_null_event(event))) |
989 | return; | 993 | return; |
990 | /* Only count data entries */ | 994 | /* Only count data entries */ |
991 | if (event->type != RINGBUF_TYPE_DATA) | 995 | if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX) |
992 | continue; | 996 | continue; |
993 | cpu_buffer->overrun++; | 997 | cpu_buffer->overrun++; |
994 | cpu_buffer->entries--; | 998 | cpu_buffer->entries--; |
@@ -1133,28 +1137,21 @@ static void | |||
1133 | rb_update_event(struct ring_buffer_event *event, | 1137 | rb_update_event(struct ring_buffer_event *event, |
1134 | unsigned type, unsigned length) | 1138 | unsigned type, unsigned length) |
1135 | { | 1139 | { |
1136 | event->type = type; | 1140 | event->type_len = type; |
1137 | 1141 | ||
1138 | switch (type) { | 1142 | switch (type) { |
1139 | 1143 | ||
1140 | case RINGBUF_TYPE_PADDING: | 1144 | case RINGBUF_TYPE_PADDING: |
1141 | break; | ||
1142 | |||
1143 | case RINGBUF_TYPE_TIME_EXTEND: | 1145 | case RINGBUF_TYPE_TIME_EXTEND: |
1144 | event->len = DIV_ROUND_UP(RB_LEN_TIME_EXTEND, RB_ALIGNMENT); | ||
1145 | break; | ||
1146 | |||
1147 | case RINGBUF_TYPE_TIME_STAMP: | 1146 | case RINGBUF_TYPE_TIME_STAMP: |
1148 | event->len = DIV_ROUND_UP(RB_LEN_TIME_STAMP, RB_ALIGNMENT); | ||
1149 | break; | 1147 | break; |
1150 | 1148 | ||
1151 | case RINGBUF_TYPE_DATA: | 1149 | case 0: |
1152 | length -= RB_EVNT_HDR_SIZE; | 1150 | length -= RB_EVNT_HDR_SIZE; |
1153 | if (length > RB_MAX_SMALL_DATA) { | 1151 | if (length > RB_MAX_SMALL_DATA) |
1154 | event->len = 0; | ||
1155 | event->array[0] = length; | 1152 | event->array[0] = length; |
1156 | } else | 1153 | else |
1157 | event->len = DIV_ROUND_UP(length, RB_ALIGNMENT); | 1154 | event->type_len = DIV_ROUND_UP(length, RB_ALIGNMENT); |
1158 | break; | 1155 | break; |
1159 | default: | 1156 | default: |
1160 | BUG(); | 1157 | BUG(); |
@@ -1562,7 +1559,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, unsigned long length) | |||
1562 | if (length > BUF_PAGE_SIZE) | 1559 | if (length > BUF_PAGE_SIZE) |
1563 | goto out; | 1560 | goto out; |
1564 | 1561 | ||
1565 | event = rb_reserve_next_event(cpu_buffer, RINGBUF_TYPE_DATA, length); | 1562 | event = rb_reserve_next_event(cpu_buffer, 0, length); |
1566 | if (!event) | 1563 | if (!event) |
1567 | goto out; | 1564 | goto out; |
1568 | 1565 | ||
@@ -1634,7 +1631,9 @@ EXPORT_SYMBOL_GPL(ring_buffer_unlock_commit); | |||
1634 | 1631 | ||
1635 | static inline void rb_event_discard(struct ring_buffer_event *event) | 1632 | static inline void rb_event_discard(struct ring_buffer_event *event) |
1636 | { | 1633 | { |
1637 | event->type = RINGBUF_TYPE_PADDING; | 1634 | /* array[0] holds the actual length for the discarded event */ |
1635 | event->array[0] = rb_event_data_length(event) - RB_EVNT_HDR_SIZE; | ||
1636 | event->type_len = RINGBUF_TYPE_PADDING; | ||
1638 | /* time delta must be non zero */ | 1637 | /* time delta must be non zero */ |
1639 | if (!event->time_delta) | 1638 | if (!event->time_delta) |
1640 | event->time_delta = 1; | 1639 | event->time_delta = 1; |
@@ -1786,8 +1785,7 @@ int ring_buffer_write(struct ring_buffer *buffer, | |||
1786 | goto out; | 1785 | goto out; |
1787 | 1786 | ||
1788 | event_length = rb_calculate_event_length(length); | 1787 | event_length = rb_calculate_event_length(length); |
1789 | event = rb_reserve_next_event(cpu_buffer, | 1788 | event = rb_reserve_next_event(cpu_buffer, 0, event_length); |
1790 | RINGBUF_TYPE_DATA, event_length); | ||
1791 | if (!event) | 1789 | if (!event) |
1792 | goto out; | 1790 | goto out; |
1793 | 1791 | ||
@@ -2035,7 +2033,7 @@ rb_update_read_stamp(struct ring_buffer_per_cpu *cpu_buffer, | |||
2035 | { | 2033 | { |
2036 | u64 delta; | 2034 | u64 delta; |
2037 | 2035 | ||
2038 | switch (event->type) { | 2036 | switch (event->type_len) { |
2039 | case RINGBUF_TYPE_PADDING: | 2037 | case RINGBUF_TYPE_PADDING: |
2040 | return; | 2038 | return; |
2041 | 2039 | ||
@@ -2066,7 +2064,7 @@ rb_update_iter_read_stamp(struct ring_buffer_iter *iter, | |||
2066 | { | 2064 | { |
2067 | u64 delta; | 2065 | u64 delta; |
2068 | 2066 | ||
2069 | switch (event->type) { | 2067 | switch (event->type_len) { |
2070 | case RINGBUF_TYPE_PADDING: | 2068 | case RINGBUF_TYPE_PADDING: |
2071 | return; | 2069 | return; |
2072 | 2070 | ||
@@ -2181,7 +2179,8 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer) | |||
2181 | 2179 | ||
2182 | event = rb_reader_event(cpu_buffer); | 2180 | event = rb_reader_event(cpu_buffer); |
2183 | 2181 | ||
2184 | if (event->type == RINGBUF_TYPE_DATA || rb_discarded_event(event)) | 2182 | if (event->type_len <= RINGBUF_TYPE_DATA_TYPE_LEN_MAX |
2183 | || rb_discarded_event(event)) | ||
2185 | cpu_buffer->entries--; | 2184 | cpu_buffer->entries--; |
2186 | 2185 | ||
2187 | rb_update_read_stamp(cpu_buffer, event); | 2186 | rb_update_read_stamp(cpu_buffer, event); |
@@ -2262,7 +2261,7 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
2262 | 2261 | ||
2263 | event = rb_reader_event(cpu_buffer); | 2262 | event = rb_reader_event(cpu_buffer); |
2264 | 2263 | ||
2265 | switch (event->type) { | 2264 | switch (event->type_len) { |
2266 | case RINGBUF_TYPE_PADDING: | 2265 | case RINGBUF_TYPE_PADDING: |
2267 | if (rb_null_event(event)) | 2266 | if (rb_null_event(event)) |
2268 | RB_WARN_ON(cpu_buffer, 1); | 2267 | RB_WARN_ON(cpu_buffer, 1); |
@@ -2334,7 +2333,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
2334 | 2333 | ||
2335 | event = rb_iter_head_event(iter); | 2334 | event = rb_iter_head_event(iter); |
2336 | 2335 | ||
2337 | switch (event->type) { | 2336 | switch (event->type_len) { |
2338 | case RINGBUF_TYPE_PADDING: | 2337 | case RINGBUF_TYPE_PADDING: |
2339 | if (rb_null_event(event)) { | 2338 | if (rb_null_event(event)) { |
2340 | rb_inc_iter(iter); | 2339 | rb_inc_iter(iter); |
@@ -2393,7 +2392,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
2393 | event = rb_buffer_peek(buffer, cpu, ts); | 2392 | event = rb_buffer_peek(buffer, cpu, ts); |
2394 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2393 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
2395 | 2394 | ||
2396 | if (event && event->type == RINGBUF_TYPE_PADDING) { | 2395 | if (event && event->type_len == RINGBUF_TYPE_PADDING) { |
2397 | cpu_relax(); | 2396 | cpu_relax(); |
2398 | goto again; | 2397 | goto again; |
2399 | } | 2398 | } |
@@ -2421,7 +2420,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
2421 | event = rb_iter_peek(iter, ts); | 2420 | event = rb_iter_peek(iter, ts); |
2422 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2421 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
2423 | 2422 | ||
2424 | if (event && event->type == RINGBUF_TYPE_PADDING) { | 2423 | if (event && event->type_len == RINGBUF_TYPE_PADDING) { |
2425 | cpu_relax(); | 2424 | cpu_relax(); |
2426 | goto again; | 2425 | goto again; |
2427 | } | 2426 | } |
@@ -2466,7 +2465,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
2466 | out: | 2465 | out: |
2467 | preempt_enable(); | 2466 | preempt_enable(); |
2468 | 2467 | ||
2469 | if (event && event->type == RINGBUF_TYPE_PADDING) { | 2468 | if (event && event->type_len == RINGBUF_TYPE_PADDING) { |
2470 | cpu_relax(); | 2469 | cpu_relax(); |
2471 | goto again; | 2470 | goto again; |
2472 | } | 2471 | } |
@@ -2559,7 +2558,7 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) | |||
2559 | out: | 2558 | out: |
2560 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 2559 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
2561 | 2560 | ||
2562 | if (event && event->type == RINGBUF_TYPE_PADDING) { | 2561 | if (event && event->type_len == RINGBUF_TYPE_PADDING) { |
2563 | cpu_relax(); | 2562 | cpu_relax(); |
2564 | goto again; | 2563 | goto again; |
2565 | } | 2564 | } |
@@ -2766,7 +2765,7 @@ static void rb_remove_entries(struct ring_buffer_per_cpu *cpu_buffer, | |||
2766 | if (RB_WARN_ON(cpu_buffer, rb_null_event(event))) | 2765 | if (RB_WARN_ON(cpu_buffer, rb_null_event(event))) |
2767 | return; | 2766 | return; |
2768 | /* Only count data entries */ | 2767 | /* Only count data entries */ |
2769 | if (event->type != RINGBUF_TYPE_DATA) | 2768 | if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX) |
2770 | continue; | 2769 | continue; |
2771 | cpu_buffer->entries--; | 2770 | cpu_buffer->entries--; |
2772 | } | 2771 | } |