mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-25 18:59:33 +03:00
* modules/spl/spl-kmem.c : Make sure to disable interrupts
when necessary to avoid deadlocks. We were seeing the deadlock when calling kmem_cache_generic_constructor() and then an interrupt forced us to end up calling kmem_cache_generic_destructor() which caused our deadlock. git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@74 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
parent
d61e12af5a
commit
55152ebbb4
@ -1,3 +1,11 @@
|
||||
2008-04-16 Herb Wartens <wartens2@llnl.gov>
|
||||
|
||||
* modules/spl/spl-kmem.c : Make sure to disable interrupts
|
||||
when necessary to avoid deadlocks. We were seeing the deadlock
|
||||
when calling kmem_cache_generic_constructor() and then an interrupt
|
||||
forced us to end up calling kmem_cache_generic_destructor()
|
||||
which caused our deadlock.
|
||||
|
||||
2008-02-26 Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
|
||||
: Initial commit of the solaris porting layer (spl). Included
|
||||
|
@ -77,6 +77,7 @@ kmem_cache_add_cache_cb(kmem_cache_t *cache,
|
||||
void *priv, void *vmp)
|
||||
{
|
||||
kmem_cache_cb_t *kcc;
|
||||
unsigned long flags;
|
||||
|
||||
kcc = (kmem_cache_cb_t *)kmalloc(sizeof(*kcc), GFP_KERNEL);
|
||||
if (kcc) {
|
||||
@ -86,9 +87,9 @@ kmem_cache_add_cache_cb(kmem_cache_t *cache,
|
||||
kcc->kcc_reclaim = reclaim;
|
||||
kcc->kcc_private = priv;
|
||||
kcc->kcc_vmp = vmp;
|
||||
spin_lock(&kmem_cache_cb_lock);
|
||||
spin_lock_irqsave(&kmem_cache_cb_lock, flags);
|
||||
list_add(&kcc->kcc_list, &kmem_cache_cb_list);
|
||||
spin_unlock(&kmem_cache_cb_lock);
|
||||
spin_unlock_irqrestore(&kmem_cache_cb_lock, flags);
|
||||
}
|
||||
|
||||
return kcc;
|
||||
@ -97,9 +98,11 @@ kmem_cache_add_cache_cb(kmem_cache_t *cache,
|
||||
static void
|
||||
kmem_cache_remove_cache_cb(kmem_cache_cb_t *kcc)
|
||||
{
|
||||
spin_lock(&kmem_cache_cb_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&kmem_cache_cb_lock, flags);
|
||||
list_del(&kcc->kcc_list);
|
||||
spin_unlock(&kmem_cache_cb_lock);
|
||||
spin_unlock_irqrestore(&kmem_cache_cb_lock, flags);
|
||||
|
||||
if (kcc)
|
||||
kfree(kcc);
|
||||
@ -110,9 +113,10 @@ kmem_cache_generic_constructor(void *ptr, kmem_cache_t *cache, unsigned long fla
|
||||
{
|
||||
kmem_cache_cb_t *kcc;
|
||||
kmem_constructor_t constructor;
|
||||
unsigned long irqflags;
|
||||
void *private;
|
||||
|
||||
spin_lock(&kmem_cache_cb_lock);
|
||||
spin_lock_irqsave(&kmem_cache_cb_lock, irqflags);
|
||||
|
||||
/* Callback list must be in sync with linux slab caches */
|
||||
kcc = kmem_cache_find_cache_cb(cache);
|
||||
@ -120,7 +124,7 @@ kmem_cache_generic_constructor(void *ptr, kmem_cache_t *cache, unsigned long fla
|
||||
constructor = kcc->kcc_constructor;
|
||||
private = kcc->kcc_private;
|
||||
|
||||
spin_unlock(&kmem_cache_cb_lock);
|
||||
spin_unlock_irqrestore(&kmem_cache_cb_lock, irqflags);
|
||||
|
||||
if (constructor)
|
||||
constructor(ptr, private, (int)flags);
|
||||
@ -133,9 +137,10 @@ kmem_cache_generic_destructor(void *ptr, kmem_cache_t *cache, unsigned long flag
|
||||
{
|
||||
kmem_cache_cb_t *kcc;
|
||||
kmem_destructor_t destructor;
|
||||
unsigned long irqflags;
|
||||
void *private;
|
||||
|
||||
spin_lock(&kmem_cache_cb_lock);
|
||||
spin_lock_irqsave(&kmem_cache_cb_lock, irqflags);
|
||||
|
||||
/* Callback list must be in sync with linux slab caches */
|
||||
kcc = kmem_cache_find_cache_cb(cache);
|
||||
@ -143,7 +148,7 @@ kmem_cache_generic_destructor(void *ptr, kmem_cache_t *cache, unsigned long flag
|
||||
destructor = kcc->kcc_destructor;
|
||||
private = kcc->kcc_private;
|
||||
|
||||
spin_unlock(&kmem_cache_cb_lock);
|
||||
spin_unlock_irqrestore(&kmem_cache_cb_lock, irqflags);
|
||||
|
||||
/* Solaris destructor takes no flags, silently eat them */
|
||||
if (destructor)
|
||||
@ -155,6 +160,7 @@ static int
|
||||
kmem_cache_generic_shrinker(int nr_to_scan, unsigned int gfp_mask)
|
||||
{
|
||||
kmem_cache_cb_t *kcc;
|
||||
unsigned long flags;
|
||||
int total = 0;
|
||||
|
||||
/* Under linux a shrinker is not tightly coupled with a slab
|
||||
@ -164,7 +170,7 @@ kmem_cache_generic_shrinker(int nr_to_scan, unsigned int gfp_mask)
|
||||
* function in the shim layer for all slab caches. And we always
|
||||
* attempt to shrink all caches when this generic shrinker is called.
|
||||
*/
|
||||
spin_lock(&kmem_cache_cb_lock);
|
||||
spin_lock_irqsave(&kmem_cache_cb_lock, flags);
|
||||
|
||||
list_for_each_entry(kcc, &kmem_cache_cb_list, kcc_list) {
|
||||
/* Under linux the desired number and gfp type of objects
|
||||
@ -185,7 +191,7 @@ kmem_cache_generic_shrinker(int nr_to_scan, unsigned int gfp_mask)
|
||||
* was registered with the generic shrinker. This should fake out
|
||||
* the linux VM when it attempts to shrink caches.
|
||||
*/
|
||||
spin_unlock(&kmem_cache_cb_lock);
|
||||
spin_unlock_irqrestore(&kmem_cache_cb_lock, flags);
|
||||
return total;
|
||||
}
|
||||
|
||||
@ -257,11 +263,12 @@ __kmem_cache_destroy(kmem_cache_t *cache)
|
||||
{
|
||||
kmem_cache_cb_t *kcc;
|
||||
char *name;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
spin_lock(&kmem_cache_cb_lock);
|
||||
spin_lock_irqsave(&kmem_cache_cb_lock, flags);
|
||||
kcc = kmem_cache_find_cache_cb(cache);
|
||||
spin_unlock(&kmem_cache_cb_lock);
|
||||
spin_unlock_irqrestore(&kmem_cache_cb_lock, flags);
|
||||
if (kcc == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
@ -271,11 +278,11 @@ __kmem_cache_destroy(kmem_cache_t *cache)
|
||||
kfree(name);
|
||||
|
||||
/* Unregister generic shrinker on removal of all caches */
|
||||
spin_lock(&kmem_cache_cb_lock);
|
||||
spin_lock_irqsave(&kmem_cache_cb_lock, flags);
|
||||
if (list_empty(&kmem_cache_cb_list))
|
||||
remove_shrinker(kmem_cache_shrinker);
|
||||
|
||||
spin_unlock(&kmem_cache_cb_lock);
|
||||
spin_unlock_irqrestore(&kmem_cache_cb_lock, flags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(__kmem_cache_destroy);
|
||||
|
Loading…
Reference in New Issue
Block a user