销毁SLUB高速缓存kmem_cache_destroy()
作者:李万鹏 于北京 borqs
SLUB分配器调用kmem_cache_destroy()来释放cache。
void kmem_cache_destroy(struct kmem_cache *s)
{
down_write(&slub_lock);
/*减少cache的引用计数*/
s->refcount--;
/*如果cache没有被使用了,比如被复用*/
if (!s->refcount) {
/*从slab_caches链表删除这个cache*/
list_del(&s->list);
/*释放cache占用的资源*/
if (kmem_cache_close(s)) {
printk(KERN_ERR "SLUB %s: %s called for cache that "
"still has objects.\n", s->name, __func__);
dump_stack();
}
if (s->flags & SLAB_DESTROY_BY_RCU)
rcu_barrier();
sysfs_slab_remove(s);
}
up_write(&slub_lock);
}
EXPORT_SYMBOL(kmem_cache_destroy);
static inline int kmem_cache_close(struct kmem_cache *s)
{
int node;
/*将所有的cpu local slab释放回 cache*/
flush_all(s);
free_percpu(s->cpu_slab);
/*循环释放每个节点的slabs_partial*/
for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = get_node(s, node);
free_partial(s, n);
if (n->nr_partial || slabs_node(s, node))
return 1;
}
free_kmem_cache_nodes(s);
return 0;
}
static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
{
unsigned long flags;
struct page *page, *h;
spin_lock_irqsave(&n->list_lock, flags);
list_for_each_entry_safe(page, h, &n->partial, lru) {
if (!page->inuse) {
/*减少节点上slab的个数*/
__remove_partial(n, page);
/*销毁slab块*/
discard_slab(s, page);
} else {
list_slab_objects(s, page,
"Objects remaining on kmem_cache_close()");
}
}
spin_unlock_irqrestore(&n->list_lock, flags);
}