| 2347 | */ |
| 2348 | #define LOCAL_SAVE 10 |
| 2349 | static void |
| 2350 | tcp_log_dumpbucketlogs(struct tcp_log_id_bucket *tlb, char *reason) |
| 2351 | { |
| 2352 | struct tcp_log_id_node local_entries[LOCAL_SAVE]; |
| 2353 | struct inpcb *inp; |
| 2354 | struct tcpcb *tp; |
| 2355 | struct tcp_log_id_node *cur_tln, *prev_tln, *tmp_tln; |
| 2356 | int i, num_local_entries, tree_locked; |
| 2357 | bool expireq_locked; |
| 2358 | |
| 2359 | TCPID_BUCKET_LOCK_ASSERT(tlb); |
| 2360 | |
| 2361 | /* |
| 2362 | * Take a reference on the bucket to keep it from disappearing until |
| 2363 | * we are done. |
| 2364 | */ |
| 2365 | TCPID_BUCKET_REF(tlb); |
| 2366 | |
| 2367 | /* |
| 2368 | * We'll try to create these without dropping locks. However, we |
| 2369 | * might very well need to drop locks to get memory. If that's the |
| 2370 | * case, we'll save up to 10 on the stack, and sacrifice the rest. |
| 2371 | * (Otherwise, we need to worry about finding our place again in a |
| 2372 | * potentially changed list. It just doesn't seem worth the trouble |
| 2373 | * to do that. |
| 2374 | */ |
| 2375 | expireq_locked = false; |
| 2376 | num_local_entries = 0; |
| 2377 | prev_tln = NULL; |
| 2378 | tree_locked = TREE_UNLOCKED; |
| 2379 | SLIST_FOREACH_SAFE(cur_tln, &tlb->tlb_head, tln_list, tmp_tln) { |
| 2380 | /* |
| 2381 | * If this isn't associated with a TCPCB, we can pull it off |
| 2382 | * the list now. We need to be careful that the expire timer |
| 2383 | * hasn't already taken ownership (tln_expiretime == SBT_MAX). |
| 2384 | * If so, we let the expire timer code free the data. |
| 2385 | */ |
| 2386 | if (cur_tln->tln_closed) { |
| 2387 | no_inp: |
| 2388 | /* |
| 2389 | * Get the expireq lock so we can get a consistent |
| 2390 | * read of tln_expiretime and so we can remove this |
| 2391 | * from the expireq. |
| 2392 | */ |
| 2393 | if (!expireq_locked) { |
| 2394 | TCPLOG_EXPIREQ_LOCK(); |
| 2395 | expireq_locked = true; |
| 2396 | } |
| 2397 | |
| 2398 | /* |
| 2399 | * We ignore entries with tln_expiretime == SBT_MAX. |
| 2400 | * The expire timer code already owns those. |
| 2401 | */ |
| 2402 | KASSERT(cur_tln->tln_expiretime > (sbintime_t) 0, |
| 2403 | ("%s:%d: node on the expire queue without positive " |
| 2404 | "expire time", __func__, __LINE__)); |
| 2405 | if (cur_tln->tln_expiretime == SBT_MAX) { |
| 2406 | prev_tln = cur_tln; |
no test coverage detected