本节介绍如何销毁一个cache。
kmem_cache_destroy
void kmem_cache_destroy(struct kmem_cache *s)
{
down_write(&slub_lock);
/* cache的引用计数减一*/
s->refcount--;
/*如果引用计数为0,说明没有对象使用此cache了*/
if (!s->refcount) {
/*从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中删除*/
sysfs_slab_remove(s);
}
up_write(&slub_lock);
}
kmem_cache_close
释放cache占用的资源。
static inline int kmem_cache_close(struct kmem_cache *s)
{
int node;
/*调用flush_slab释放local slab */
flush_all(s);
/*释放percpu空间*/
free_percpu(s->cpu_slab);
/* Attempt to free all objects */
/*循环释放每个内存节点的部分满slab */
for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = get_node(s, node);
/*释放部分满slab上的所有slab */
free_partial(s, n);
/*释放完成后,计数不为0,返回错误*/
if (n->nr_partial || slabs_node(s, node))
return 1;
}
/*释放struct kmem_cache中的struct kmem_cache_node对象*/
free_kmem_cache_nodes(s);
return 0;
}
free_partial
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);
/*循环释放部分满slab链上的所有slab */
list_for_each_entry_safe(page, h, &n->partial, lru) {
if (!page->inuse) {
/*从部分满slab链删除*/
__remove_partial(n, page);
/*废除这个slab */
discard_slab(s, page);
} else {
/* slab中还有在用的对象,错误*/
list_slab_objects(s, page,
"Objects remaining on kmem_cache_close()");
}
}
spin_unlock_irqrestore(&n->list_lock, flags);
}
__remove_partial
static inline void __remove_partial(struct kmem_cache_node *n,
struct page *page)
{
/*摘链*/
list_del(&page->lru);
/*部分满slab数减一*/
n->nr_partial--;
}
discard_slab
static void discard_slab(struct kmem_cache *s, struct page *page)
{
/*更新slab数和对象数*/
dec_slabs_node(s, page_to_nid(page), page->objects);
/*释放slab */
free_slab(s, page);
}