mirror of
https://gitee.com/openharmony/kernel_linux
synced 2025-02-26 14:46:40 +00:00
mm/sl[aou]b: Extract a common function for kmem_cache_destroy
kmem_cache_destroy does basically the same in all allocators. Extract common code which is easy since we already have common mutex handling. Reviewed-by: Glauber Costa <glommer@parallels.com> Signed-off-by: Christoph Lameter <cl@linux.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
parent
7c9adf5a54
commit
945cf2b619
45
mm/slab.c
45
mm/slab.c
@ -2206,7 +2206,7 @@ static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __kmem_cache_destroy(struct kmem_cache *cachep)
|
void __kmem_cache_destroy(struct kmem_cache *cachep)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct kmem_list3 *l3;
|
struct kmem_list3 *l3;
|
||||||
@ -2763,49 +2763,10 @@ int kmem_cache_shrink(struct kmem_cache *cachep)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_shrink);
|
EXPORT_SYMBOL(kmem_cache_shrink);
|
||||||
|
|
||||||
/**
|
int __kmem_cache_shutdown(struct kmem_cache *cachep)
|
||||||
* kmem_cache_destroy - delete a cache
|
|
||||||
* @cachep: the cache to destroy
|
|
||||||
*
|
|
||||||
* Remove a &struct kmem_cache object from the slab cache.
|
|
||||||
*
|
|
||||||
* It is expected this function will be called by a module when it is
|
|
||||||
* unloaded. This will remove the cache completely, and avoid a duplicate
|
|
||||||
* cache being allocated each time a module is loaded and unloaded, if the
|
|
||||||
* module doesn't have persistent in-kernel storage across loads and unloads.
|
|
||||||
*
|
|
||||||
* The cache must be empty before calling this function.
|
|
||||||
*
|
|
||||||
* The caller must guarantee that no one will allocate memory from the cache
|
|
||||||
* during the kmem_cache_destroy().
|
|
||||||
*/
|
|
||||||
void kmem_cache_destroy(struct kmem_cache *cachep)
|
|
||||||
{
|
{
|
||||||
BUG_ON(!cachep || in_interrupt());
|
return __cache_shrink(cachep);
|
||||||
|
|
||||||
/* Find the cache in the chain of caches. */
|
|
||||||
get_online_cpus();
|
|
||||||
mutex_lock(&slab_mutex);
|
|
||||||
/*
|
|
||||||
* the chain is never empty, cache_cache is never destroyed
|
|
||||||
*/
|
|
||||||
list_del(&cachep->list);
|
|
||||||
if (__cache_shrink(cachep)) {
|
|
||||||
slab_error(cachep, "Can't free all objects");
|
|
||||||
list_add(&cachep->list, &slab_caches);
|
|
||||||
mutex_unlock(&slab_mutex);
|
|
||||||
put_online_cpus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
|
|
||||||
rcu_barrier();
|
|
||||||
|
|
||||||
__kmem_cache_destroy(cachep);
|
|
||||||
mutex_unlock(&slab_mutex);
|
|
||||||
put_online_cpus();
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_destroy);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the memory for a slab management obj.
|
* Get the memory for a slab management obj.
|
||||||
|
@ -30,4 +30,7 @@ extern struct list_head slab_caches;
|
|||||||
struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
|
struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
|
||||||
size_t align, unsigned long flags, void (*ctor)(void *));
|
size_t align, unsigned long flags, void (*ctor)(void *));
|
||||||
|
|
||||||
|
int __kmem_cache_shutdown(struct kmem_cache *);
|
||||||
|
void __kmem_cache_destroy(struct kmem_cache *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -140,6 +140,31 @@ out_locked:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_create);
|
EXPORT_SYMBOL(kmem_cache_create);
|
||||||
|
|
||||||
|
void kmem_cache_destroy(struct kmem_cache *s)
|
||||||
|
{
|
||||||
|
get_online_cpus();
|
||||||
|
mutex_lock(&slab_mutex);
|
||||||
|
s->refcount--;
|
||||||
|
if (!s->refcount) {
|
||||||
|
list_del(&s->list);
|
||||||
|
|
||||||
|
if (!__kmem_cache_shutdown(s)) {
|
||||||
|
if (s->flags & SLAB_DESTROY_BY_RCU)
|
||||||
|
rcu_barrier();
|
||||||
|
|
||||||
|
__kmem_cache_destroy(s);
|
||||||
|
} else {
|
||||||
|
list_add(&s->list, &slab_caches);
|
||||||
|
printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
|
||||||
|
s->name);
|
||||||
|
dump_stack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&slab_mutex);
|
||||||
|
put_online_cpus();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(kmem_cache_destroy);
|
||||||
|
|
||||||
int slab_is_available(void)
|
int slab_is_available(void)
|
||||||
{
|
{
|
||||||
return slab_state >= UP;
|
return slab_state >= UP;
|
||||||
|
15
mm/slob.c
15
mm/slob.c
@ -538,18 +538,11 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kmem_cache_destroy(struct kmem_cache *c)
|
void __kmem_cache_destroy(struct kmem_cache *c)
|
||||||
{
|
{
|
||||||
mutex_lock(&slab_mutex);
|
|
||||||
list_del(&c->list);
|
|
||||||
mutex_unlock(&slab_mutex);
|
|
||||||
|
|
||||||
kmemleak_free(c);
|
kmemleak_free(c);
|
||||||
if (c->flags & SLAB_DESTROY_BY_RCU)
|
|
||||||
rcu_barrier();
|
|
||||||
slob_free(c, sizeof(struct kmem_cache));
|
slob_free(c, sizeof(struct kmem_cache));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_destroy);
|
|
||||||
|
|
||||||
void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
|
void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
|
||||||
{
|
{
|
||||||
@ -617,6 +610,12 @@ unsigned int kmem_cache_size(struct kmem_cache *c)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_size);
|
EXPORT_SYMBOL(kmem_cache_size);
|
||||||
|
|
||||||
|
int __kmem_cache_shutdown(struct kmem_cache *c)
|
||||||
|
{
|
||||||
|
/* No way to check for remaining objects */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int kmem_cache_shrink(struct kmem_cache *d)
|
int kmem_cache_shrink(struct kmem_cache *d)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
36
mm/slub.c
36
mm/slub.c
@ -624,7 +624,7 @@ static void object_err(struct kmem_cache *s, struct page *page,
|
|||||||
print_trailer(s, page, object);
|
print_trailer(s, page, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
|
static void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
char buf[100];
|
char buf[100];
|
||||||
@ -3146,7 +3146,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
|
|||||||
sizeof(long), GFP_ATOMIC);
|
sizeof(long), GFP_ATOMIC);
|
||||||
if (!map)
|
if (!map)
|
||||||
return;
|
return;
|
||||||
slab_err(s, page, "%s", text);
|
slab_err(s, page, text, s->name);
|
||||||
slab_lock(page);
|
slab_lock(page);
|
||||||
|
|
||||||
get_map(s, page, map);
|
get_map(s, page, map);
|
||||||
@ -3178,7 +3178,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
|
|||||||
discard_slab(s, page);
|
discard_slab(s, page);
|
||||||
} else {
|
} else {
|
||||||
list_slab_objects(s, page,
|
list_slab_objects(s, page,
|
||||||
"Objects remaining on kmem_cache_close()");
|
"Objects remaining in %s on kmem_cache_close()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3191,7 +3191,6 @@ static inline int kmem_cache_close(struct kmem_cache *s)
|
|||||||
int node;
|
int node;
|
||||||
|
|
||||||
flush_all(s);
|
flush_all(s);
|
||||||
free_percpu(s->cpu_slab);
|
|
||||||
/* Attempt to free all objects */
|
/* Attempt to free all objects */
|
||||||
for_each_node_state(node, N_NORMAL_MEMORY) {
|
for_each_node_state(node, N_NORMAL_MEMORY) {
|
||||||
struct kmem_cache_node *n = get_node(s, node);
|
struct kmem_cache_node *n = get_node(s, node);
|
||||||
@ -3200,33 +3199,20 @@ static inline int kmem_cache_close(struct kmem_cache *s)
|
|||||||
if (n->nr_partial || slabs_node(s, node))
|
if (n->nr_partial || slabs_node(s, node))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
free_percpu(s->cpu_slab);
|
||||||
free_kmem_cache_nodes(s);
|
free_kmem_cache_nodes(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int __kmem_cache_shutdown(struct kmem_cache *s)
|
||||||
* Close a cache and release the kmem_cache structure
|
|
||||||
* (must be used for caches created using kmem_cache_create)
|
|
||||||
*/
|
|
||||||
void kmem_cache_destroy(struct kmem_cache *s)
|
|
||||||
{
|
{
|
||||||
mutex_lock(&slab_mutex);
|
return kmem_cache_close(s);
|
||||||
s->refcount--;
|
}
|
||||||
if (!s->refcount) {
|
|
||||||
list_del(&s->list);
|
void __kmem_cache_destroy(struct kmem_cache *s)
|
||||||
mutex_unlock(&slab_mutex);
|
{
|
||||||
if (kmem_cache_close(s)) {
|
sysfs_slab_remove(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);
|
|
||||||
} else
|
|
||||||
mutex_unlock(&slab_mutex);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_destroy);
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Kmalloc subsystem
|
* Kmalloc subsystem
|
||||||
|
Loading…
x
Reference in New Issue
Block a user