- When deciding whether to init the zone with small_init or large_init,

compare the zone element size (+1 for the byte of linkage) against
  UMA_SLAB_SIZE - sizeof(struct uma_slab), and not just UMA_SLAB_SIZE.
  Add a KASSERT in zone_small_init to make sure that the computed
  ipers (items per slab) for the zone is not zero, despite the addition
  of the check, just to be sure (this part submitted by: silby)

- UMA_ZONE_VM used to imply BUCKETCACHE.  Now it implies
  CACHEONLY instead.  CACHEONLY is like BUCKETCACHE in the
  case of bucket allocations, but in addition to that also ensures that
  we don't setup the zone with OFFPAGE slab headers allocated from the
  slabzone.  This means that we're not allowed to have a UMA_ZONE_VM
  zone initialized for large items (zone_large_init) because it would
  require the slab headers to be allocated from slabzone, and hence
  kmem_map.  Some of the zones init'd with UMA_ZONE_VM are so init'd
  before kmem_map is suballoc'd from kernel_map, which is why this
  change is necessary.
This commit is contained in:
Bosko Milekic 2003-08-11 19:39:45 +00:00
parent 660ebf0ef2
commit 20e8e865bd
2 changed files with 25 additions and 6 deletions

View file

@ -939,11 +939,20 @@ zone_small_init(uma_zone_t zone)
zone->uz_ipers = (UMA_SLAB_SIZE - sizeof(struct uma_slab)) / rsize;
zone->uz_ppera = 1;
KASSERT(zone->uz_ipers != 0, ("zone_small_init: ipers is 0, uh-oh!"));
memused = zone->uz_ipers * zone->uz_rsize;
/* Can we do any better? */
if ((UMA_SLAB_SIZE - memused) >= UMA_MAX_WASTE) {
if (zone->uz_flags & UMA_ZFLAG_INTERNAL)
/*
* We can't do this if we're internal or if we've been
* asked to not go to the VM for buckets. If we do this we
* may end up going to the VM (kmem_map) for slabs which we
* do not want to do if we're UMA_ZFLAG_CACHEONLY as a
* result of UMA_ZONE_VM, which clearly forbids it.
*/
if ((zone->uz_flags & UMA_ZFLAG_INTERNAL) ||
(zone->uz_flags & UMA_ZFLAG_CACHEONLY))
return;
ipers = UMA_SLAB_SIZE / zone->uz_rsize;
if (ipers > zone->uz_ipers) {
@ -972,6 +981,9 @@ zone_large_init(uma_zone_t zone)
{
int pages;
KASSERT((zone->uz_flags & UMA_ZFLAG_CACHEONLY) == 0,
("zone_large_init: Cannot large-init a UMA_ZFLAG_CACHEONLY zone"));
pages = zone->uz_size / UMA_SLAB_SIZE;
/* Account for remainder */
@ -1031,9 +1043,16 @@ zone_ctor(void *mem, int size, void *udata)
zone->uz_flags |= UMA_ZFLAG_NOFREE;
if (arg->flags & UMA_ZONE_VM)
zone->uz_flags |= UMA_ZFLAG_BUCKETCACHE;
zone->uz_flags |= UMA_ZFLAG_CACHEONLY;
if (zone->uz_size > UMA_SLAB_SIZE)
/*
* XXX:
* The +1 byte added to uz_size is to account for the byte of
* linkage that is added to the size in zone_small_init(). If
* we don't account for this here then we may end up in
* zone_small_init() with a calculated 'ipers' of 0.
*/
if ((zone->uz_size+1) > (UMA_SLAB_SIZE - sizeof(struct uma_slab)))
zone_large_init(zone);
else
zone_small_init(zone);
@ -1574,7 +1593,7 @@ uma_zalloc_bucket(uma_zone_t zone, int flags)
int bflags;
bflags = flags;
if (zone->uz_flags & UMA_ZFLAG_BUCKETCACHE)
if (zone->uz_flags & UMA_ZFLAG_CACHEONLY)
bflags |= M_NOVM;
ZONE_UNLOCK(zone);
@ -1802,7 +1821,7 @@ zfree_start:
#endif
bflags = M_NOWAIT;
if (zone->uz_flags & UMA_ZFLAG_BUCKETCACHE)
if (zone->uz_flags & UMA_ZFLAG_CACHEONLY)
bflags |= M_NOVM;
#ifdef INVARIANTS
bflags |= M_ZERO;

View file

@ -260,7 +260,7 @@ struct uma_zone {
#define UMA_ZFLAG_MALLOC 0x0008 /* Zone created by malloc */
#define UMA_ZFLAG_NOFREE 0x0010 /* Don't free data from this zone */
#define UMA_ZFLAG_FULL 0x0020 /* This zone reached uz_maxpages */
#define UMA_ZFLAG_BUCKETCACHE 0x0040 /* Only allocate buckets from cache */
#define UMA_ZFLAG_CACHEONLY 0x0040 /* Don't go to VM to allocate internal objs */
#define UMA_ZFLAG_HASH 0x0080 /* Look up slab via hash */
/* This lives in uflags */