static int check_slab(struct kmem_cache *s, struct page *page) { int maxobj; VM_BUG_ON(!irqs_disabled()); if (!PageSlab(page)) { slab_err(s, page, "Not a valid slab page"); return 0; } maxobj = order_objects(compound_order(page), s->size, s->reserved); if (page->objects > maxobj) { slab_err(s, page, "objects %u > max %u", s->name, page->objects, maxobj); return 0; } if (page->inuse > page->objects) { slab_err(s, page, "inuse %u > max %u", s->name, page->inuse, page->objects); return 0; } /* Slab_pad_check fixes things up after itself */ slab_pad_check(s, page); return 1; }
/* 给定最小objects数目要求和最大order计算较合适的order */ static int slab_order(int size, int min_objects, int max_order, int fract_leftover) { int order; int rem; int min_order = slub_min_order; /* 当前最小order下对象太多了 */ if (order_objects(min_order, size) > MAX_OBJS_PER_PAGE) return get_order(size * MAX_OBJS_PER_PAGE) - 1; for (order = max(min_order, /* 找到最低对齐位对应的order,然后和最小order选个最大的 */ fls(min_objects * size - 1) - PAGE_SHIFT); order <= max_order; order++) { unsigned long slab_size = PAGE_SIZE << order; /* slab太小了 */ if (slab_size < min_objects * size) continue; /* 计算剩余字节数 */ rem = (slab_size) % size; /* 剩余字节数满足要求,也就是最大不浪费总共大小的四分之一 */ if (rem <= slab_size / fract_leftover) break; } return order; }
static inline struct kmem_cache_order_objects oo_make(int order, unsigned long size, int reserved) { struct kmem_cache_order_objects x = { (order << OO_SHIFT) + order_objects(order, size, reserved) }; return x; }
/* * Determine if a certain object on a page is on the freelist. Must hold the * slab lock to guarantee that the chains are in a consistent state. */ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) { int nr = 0; void *fp; void *object = NULL; unsigned long max_objects; fp = page->freelist; while (fp && nr <= page->objects) { if (fp == search) return 1; if (!check_valid_pointer(s, page, fp)) { if (object) { object_err(s, page, object, "Freechain corrupt"); set_freepointer(s, object, NULL); break; } else { slab_err(s, page, "Freepointer corrupt"); page->freelist = NULL; page->inuse = page->objects; slab_fix(s, "Freelist cleared"); return 0; } break; } object = fp; fp = get_freepointer(s, object); nr++; } max_objects = order_objects(compound_order(page), s->size, s->reserved); if (max_objects > MAX_OBJS_PER_PAGE) max_objects = MAX_OBJS_PER_PAGE; if (page->objects != max_objects) { slab_err(s, page, "Wrong number of objects. Found %d but " "should be %d", page->objects, max_objects); page->objects = max_objects; slab_fix(s, "Number of objects adjusted."); } if (page->inuse != page->objects - nr) { slab_err(s, page, "Wrong object count. Counter is %d but " "counted were %d", page->inuse, page->objects - nr); page->inuse = page->objects - nr; slab_fix(s, "Object count adjusted."); } return search == NULL; }
static int calculate_order(int size) { int order; int min_objects; int fraction; int max_objects; /* 计算最小允许的object数目和最大的object数目 */ min_objects = slub_min_objects; if (!min_objects) min_objects = MIN_OBJECT; max_objects = order_objects(slub_max_order, size); min_objects = min(min_objects, max_objects); /* 还是不行,缩小最小对象的要求 */ while (min_objects > 1) { fraction = 16; while (fraction >= 4) { /* 给定size和最小object数目计算order */ order = slab_order(size, min_objects, slub_max_order, fraction); /* 该size和objects数目计算出的order比较适合 */ if (order <= slub_max_order) return order; /* 降低粒度,也就是允许更多的浪费 */ fraction /= 2; } min_objects--; } /* 尝试将单个对象放入给定块中 */ order = slab_order(size, 1, slub_max_order, 1); if (order <= slub_max_order) return order; /* 尝试是否能放入最大的order */ order = slab_order(size, 1, MAX_ORDER, 1); if (order < MAX_ORDER) return order; return -1; }