uma: Enforce the use of uz_bucket_size_max in the free path
uz_bucket_size_max is the maximum permitted bucket size. When filling a new bucket to satisfy uma_zalloc(), the bucket is populated with at most uz_bucket_size_max items. The maximum number of entries in the bucket may be larger. When freeing items, however, we will fill per-CPPU buckets up to their maximum number of entries, potentially exceeding uz_bucket_size_max. This makes it difficult to precisely limit the number of items that may be cached in a zone. For example, if one wants to limit buckets to 1 entry for a particular zone, that's not possible since the smallest bucket holds up to 2 entries. Try to solve the problem by using uz_bucket_size_max to limit the number of entries in a bucket. Note that the ub_entries field is initialized upon every bucket allocation. Most zones are not affected since they do not impose any specific limit on the maximum bucket size. While here, remove the UMA_ZONE_MINBUCKET flag. It was unused and we now have uma_zone_set_maxcache() to control the zone's cache size more precisely. Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D27167
This commit is contained in:
parent
13b815c01a
commit
2dca52f047
@ -250,7 +250,6 @@ uma_zone_t uma_zcache_create(const char *name, int size, uma_ctor ctor,
|
||||
#define UMA_ZONE_SECONDARY 0x0200 /* Zone is a Secondary Zone */
|
||||
#define UMA_ZONE_NOBUCKET 0x0400 /* Do not use buckets. */
|
||||
#define UMA_ZONE_MAXBUCKET 0x0800 /* Use largest buckets. */
|
||||
#define UMA_ZONE_MINBUCKET 0x1000 /* Use smallest buckets. */
|
||||
#define UMA_ZONE_CACHESPREAD 0x2000 /*
|
||||
* Spread memory start locations across
|
||||
* all possible cache lines. May
|
||||
|
@ -248,7 +248,6 @@ struct uma_bucket_zone {
|
||||
(((sizeof(void *) * (n)) - sizeof(struct uma_bucket)) / sizeof(void *))
|
||||
|
||||
#define BUCKET_MAX BUCKET_SIZE(256)
|
||||
#define BUCKET_MIN 2
|
||||
|
||||
struct uma_bucket_zone bucket_zones[] = {
|
||||
/* Literal bucket sizes. */
|
||||
@ -507,7 +506,7 @@ bucket_alloc(uma_zone_t zone, void *udata, int flags)
|
||||
}
|
||||
if (((uintptr_t)udata & UMA_ZONE_VM) != 0)
|
||||
flags |= M_NOVM;
|
||||
ubz = bucket_zone_lookup(zone->uz_bucket_size);
|
||||
ubz = bucket_zone_lookup(atomic_load_16(&zone->uz_bucket_size));
|
||||
if (ubz->ubz_zone == zone && (ubz + 1)->ubz_entries != 0)
|
||||
ubz++;
|
||||
bucket = uma_zalloc_arg(ubz->ubz_zone, udata, flags);
|
||||
@ -516,7 +515,8 @@ bucket_alloc(uma_zone_t zone, void *udata, int flags)
|
||||
bzero(bucket->ub_bucket, sizeof(void *) * ubz->ubz_entries);
|
||||
#endif
|
||||
bucket->ub_cnt = 0;
|
||||
bucket->ub_entries = ubz->ubz_entries;
|
||||
bucket->ub_entries = min(ubz->ubz_entries,
|
||||
zone->uz_bucket_size_max);
|
||||
bucket->ub_seq = SMR_SEQ_INVALID;
|
||||
CTR3(KTR_UMA, "bucket_alloc: zone %s(%p) allocated bucket %p",
|
||||
zone->uz_name, zone, bucket);
|
||||
@ -2724,8 +2724,6 @@ zone_ctor(void *mem, int size, void *udata, int flags)
|
||||
zone->uz_bucket_size_max = zone->uz_bucket_size = 0;
|
||||
if ((arg->flags & UMA_ZONE_MAXBUCKET) != 0)
|
||||
zone->uz_bucket_size = BUCKET_MAX;
|
||||
else if ((arg->flags & UMA_ZONE_MINBUCKET) != 0)
|
||||
zone->uz_bucket_size_max = zone->uz_bucket_size = BUCKET_MIN;
|
||||
else if ((arg->flags & UMA_ZONE_NOBUCKET) != 0)
|
||||
zone->uz_bucket_size = 0;
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user