| 457 | } |
| 458 | |
| 459 | static uma_bucket_t |
| 460 | bucket_alloc(uma_zone_t zone, void *udata, int flags) |
| 461 | { |
| 462 | struct uma_bucket_zone *ubz; |
| 463 | uma_bucket_t bucket; |
| 464 | |
| 465 | /* |
| 466 | * Don't allocate buckets early in boot. |
| 467 | */ |
| 468 | if (__predict_false(booted < BOOT_KVA)) |
| 469 | return (NULL); |
| 470 | |
| 471 | /* |
| 472 | * To limit bucket recursion we store the original zone flags |
| 473 | * in a cookie passed via zalloc_arg/zfree_arg. This allows the |
| 474 | * NOVM flag to persist even through deep recursions. We also |
| 475 | * store ZFLAG_BUCKET once we have recursed attempting to allocate |
| 476 | * a bucket for a bucket zone so we do not allow infinite bucket |
| 477 | * recursion. This cookie will even persist to frees of unused |
| 478 | * buckets via the allocation path or bucket allocations in the |
| 479 | * free path. |
| 480 | */ |
| 481 | if ((zone->uz_flags & UMA_ZFLAG_BUCKET) == 0) |
| 482 | udata = (void *)(uintptr_t)zone->uz_flags; |
| 483 | else { |
| 484 | if ((uintptr_t)udata & UMA_ZFLAG_BUCKET) |
| 485 | return (NULL); |
| 486 | udata = (void *)((uintptr_t)udata | UMA_ZFLAG_BUCKET); |
| 487 | } |
| 488 | if (((uintptr_t)udata & UMA_ZONE_VM) != 0) |
| 489 | flags |= M_NOVM; |
| 490 | ubz = bucket_zone_lookup(atomic_load_16(&zone->uz_bucket_size)); |
| 491 | if (ubz->ubz_zone == zone && (ubz + 1)->ubz_entries != 0) |
| 492 | ubz++; |
| 493 | bucket = uma_zalloc_arg(ubz->ubz_zone, udata, flags); |
| 494 | if (bucket) { |
| 495 | #ifdef INVARIANTS |
| 496 | bzero(bucket->ub_bucket, sizeof(void *) * ubz->ubz_entries); |
| 497 | #endif |
| 498 | bucket->ub_cnt = 0; |
| 499 | bucket->ub_entries = min(ubz->ubz_entries, |
| 500 | zone->uz_bucket_size_max); |
| 501 | bucket->ub_seq = SMR_SEQ_INVALID; |
| 502 | CTR3(KTR_UMA, "bucket_alloc: zone %s(%p) allocated bucket %p", |
| 503 | zone->uz_name, zone, bucket); |
| 504 | } |
| 505 | |
| 506 | return (bucket); |
| 507 | } |
| 508 | |
| 509 | static void |
| 510 | bucket_free(uma_zone_t zone, uma_bucket_t bucket, void *udata) |
no test coverage detected