| 1397 | } |
| 1398 | |
| 1399 | static void |
| 1400 | keg_drain_domain(uma_keg_t keg, int domain) |
| 1401 | { |
| 1402 | struct slabhead freeslabs; |
| 1403 | uma_domain_t dom; |
| 1404 | uma_slab_t slab, tmp; |
| 1405 | uint32_t i, stofree, stokeep, partial; |
| 1406 | |
| 1407 | dom = &keg->uk_domain[domain]; |
| 1408 | LIST_INIT(&freeslabs); |
| 1409 | |
| 1410 | CTR4(KTR_UMA, "keg_drain %s(%p) domain %d free items: %u", |
| 1411 | keg->uk_name, keg, domain, dom->ud_free_items); |
| 1412 | |
| 1413 | KEG_LOCK(keg, domain); |
| 1414 | |
| 1415 | /* |
| 1416 | * Are the free items in partially allocated slabs sufficient to meet |
| 1417 | * the reserve? If not, compute the number of fully free slabs that must |
| 1418 | * be kept. |
| 1419 | */ |
| 1420 | partial = dom->ud_free_items - dom->ud_free_slabs * keg->uk_ipers; |
| 1421 | if (partial < keg->uk_reserve) { |
| 1422 | stokeep = min(dom->ud_free_slabs, |
| 1423 | howmany(keg->uk_reserve - partial, keg->uk_ipers)); |
| 1424 | } else { |
| 1425 | stokeep = 0; |
| 1426 | } |
| 1427 | stofree = dom->ud_free_slabs - stokeep; |
| 1428 | |
| 1429 | /* |
| 1430 | * Partition the free slabs into two sets: those that must be kept in |
| 1431 | * order to maintain the reserve, and those that may be released back to |
| 1432 | * the system. Since one set may be much larger than the other, |
| 1433 | * populate the smaller of the two sets and swap them if necessary. |
| 1434 | */ |
| 1435 | for (i = min(stofree, stokeep); i > 0; i--) { |
| 1436 | slab = LIST_FIRST(&dom->ud_free_slab); |
| 1437 | LIST_REMOVE(slab, us_link); |
| 1438 | LIST_INSERT_HEAD(&freeslabs, slab, us_link); |
| 1439 | } |
| 1440 | if (stofree > stokeep) |
| 1441 | LIST_SWAP(&freeslabs, &dom->ud_free_slab, uma_slab, us_link); |
| 1442 | |
| 1443 | if ((keg->uk_flags & UMA_ZFLAG_HASH) != 0) { |
| 1444 | LIST_FOREACH(slab, &freeslabs, us_link) |
| 1445 | UMA_HASH_REMOVE(&keg->uk_hash, slab); |
| 1446 | } |
| 1447 | dom->ud_free_items -= stofree * keg->uk_ipers; |
| 1448 | dom->ud_free_slabs -= stofree; |
| 1449 | dom->ud_pages -= stofree * keg->uk_ppera; |
| 1450 | KEG_UNLOCK(keg, domain); |
| 1451 | |
| 1452 | LIST_FOREACH_SAFE(slab, &freeslabs, us_link, tmp) |
| 1453 | keg_free_slab(keg, slab, keg->uk_ipers); |
| 1454 | } |
| 1455 | |
| 1456 | /* |
no test coverage detected