全部博文(50)
分类: LINUX
2014-04-04 11:54:03
原文地址:Vi Linux内存 之 Slub分配器(七) 作者:palals
本节介绍如何销毁一个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);
}