Stability hack. Under Solaris when KM_SLEEP is set kmem_cache_alloc()
may not fail. To get this behavior I'd added a retry to the shim layer even though it is abusive to the VM, at least it should prevent the crash. Additionally I added a proc counter so I can easily check how often this is happening. It should be fairly rare, but likely will get worse and worse the longer the machine has been up. git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@104 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
parent
04a479f706
commit
5c2bb9b2c3
|
@ -32,7 +32,9 @@ extern atomic64_t kmem_alloc_used;
|
||||||
extern unsigned long kmem_alloc_max;
|
extern unsigned long kmem_alloc_max;
|
||||||
extern atomic64_t vmem_alloc_used;
|
extern atomic64_t vmem_alloc_used;
|
||||||
extern unsigned long vmem_alloc_max;
|
extern unsigned long vmem_alloc_max;
|
||||||
|
|
||||||
extern int kmem_warning_flag;
|
extern int kmem_warning_flag;
|
||||||
|
extern atomic64_t kmem_cache_alloc_failed;
|
||||||
|
|
||||||
#define KMEM_HASH_BITS 10
|
#define KMEM_HASH_BITS 10
|
||||||
#define KMEM_TABLE_SIZE (1 << KMEM_HASH_BITS)
|
#define KMEM_TABLE_SIZE (1 << KMEM_HASH_BITS)
|
||||||
|
@ -351,11 +353,9 @@ __kmem_cache_create(char *name, size_t size, size_t align,
|
||||||
kmem_reclaim_t reclaim,
|
kmem_reclaim_t reclaim,
|
||||||
void *priv, void *vmp, int flags);
|
void *priv, void *vmp, int flags);
|
||||||
|
|
||||||
int
|
extern int __kmem_cache_destroy(kmem_cache_t *cache);
|
||||||
extern __kmem_cache_destroy(kmem_cache_t *cache);
|
extern void *__kmem_cache_alloc(kmem_cache_t *cache, gfp_t flags);
|
||||||
|
extern void __kmem_reap(void);
|
||||||
void
|
|
||||||
extern __kmem_reap(void);
|
|
||||||
|
|
||||||
int kmem_init(void);
|
int kmem_init(void);
|
||||||
void kmem_fini(void);
|
void kmem_fini(void);
|
||||||
|
@ -363,7 +363,7 @@ void kmem_fini(void);
|
||||||
#define kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) \
|
#define kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) \
|
||||||
__kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags)
|
__kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags)
|
||||||
#define kmem_cache_destroy(cache) __kmem_cache_destroy(cache)
|
#define kmem_cache_destroy(cache) __kmem_cache_destroy(cache)
|
||||||
#define kmem_cache_alloc(cache, flags) kmem_cache_alloc(cache, flags)
|
#define kmem_cache_alloc(cache, flags) __kmem_cache_alloc(cache, flags)
|
||||||
#define kmem_cache_free(cache, ptr) kmem_cache_free(cache, ptr)
|
#define kmem_cache_free(cache, ptr) kmem_cache_free(cache, ptr)
|
||||||
#define kmem_cache_reap_now(cache) kmem_cache_shrink(cache)
|
#define kmem_cache_reap_now(cache) kmem_cache_shrink(cache)
|
||||||
#define kmem_reap() __kmem_reap()
|
#define kmem_reap() __kmem_reap()
|
||||||
|
|
|
@ -16,6 +16,7 @@ unsigned long kmem_alloc_max = 0;
|
||||||
atomic64_t vmem_alloc_used;
|
atomic64_t vmem_alloc_used;
|
||||||
unsigned long vmem_alloc_max = 0;
|
unsigned long vmem_alloc_max = 0;
|
||||||
int kmem_warning_flag = 1;
|
int kmem_warning_flag = 1;
|
||||||
|
atomic64_t kmem_cache_alloc_failed;
|
||||||
|
|
||||||
spinlock_t kmem_lock;
|
spinlock_t kmem_lock;
|
||||||
struct hlist_head kmem_table[KMEM_TABLE_SIZE];
|
struct hlist_head kmem_table[KMEM_TABLE_SIZE];
|
||||||
|
@ -268,6 +269,7 @@ kmem_cache_generic_shrinker(int nr_to_scan, unsigned int gfp_mask)
|
||||||
*/
|
*/
|
||||||
#undef kmem_cache_create
|
#undef kmem_cache_create
|
||||||
#undef kmem_cache_destroy
|
#undef kmem_cache_destroy
|
||||||
|
#undef kmem_cache_alloc
|
||||||
|
|
||||||
kmem_cache_t *
|
kmem_cache_t *
|
||||||
__kmem_cache_create(char *name, size_t size, size_t align,
|
__kmem_cache_create(char *name, size_t size, size_t align,
|
||||||
|
@ -360,6 +362,30 @@ __kmem_cache_destroy(kmem_cache_t *cache)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__kmem_cache_destroy);
|
EXPORT_SYMBOL(__kmem_cache_destroy);
|
||||||
|
|
||||||
|
/* Under Solaris if the KM_SLEEP flag is passed we absolutely must
|
||||||
|
* sleep until we are allocated the memory. Under Linux you can still
|
||||||
|
* get a memory allocation failure, so I'm forced to keep requesting
|
||||||
|
* the memory even if the system is under substantial memory pressure
|
||||||
|
* of fragmentation prevents the allocation from succeeded. This is
|
||||||
|
* not the correct fix, or even a good one. But it will do for now.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
__kmem_cache_alloc(kmem_cache_t *cache, gfp_t flags)
|
||||||
|
{
|
||||||
|
void *rc;
|
||||||
|
ENTRY;
|
||||||
|
|
||||||
|
restart:
|
||||||
|
rc = kmem_cache_alloc(cache, flags);
|
||||||
|
if ((rc == NULL) && (flags & KM_SLEEP)) {
|
||||||
|
atomic64_inc(&kmem_cache_alloc_failed);
|
||||||
|
GOTO(restart, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN(rc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__kmem_cache_alloc);
|
||||||
|
|
||||||
void
|
void
|
||||||
__kmem_reap(void)
|
__kmem_reap(void)
|
||||||
{
|
{
|
||||||
|
@ -395,6 +421,8 @@ kmem_init(void)
|
||||||
|
|
||||||
for (i = 0; i < VMEM_TABLE_SIZE; i++)
|
for (i = 0; i < VMEM_TABLE_SIZE; i++)
|
||||||
INIT_HLIST_HEAD(&vmem_table[i]);
|
INIT_HLIST_HEAD(&vmem_table[i]);
|
||||||
|
|
||||||
|
atomic64_set(&kmem_cache_alloc_failed, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
RETURN(0);
|
RETURN(0);
|
||||||
|
|
|
@ -60,6 +60,7 @@ enum {
|
||||||
CTL_KMEM_KMEMMAX, /* Max alloc'd by kmem bytes */
|
CTL_KMEM_KMEMMAX, /* Max alloc'd by kmem bytes */
|
||||||
CTL_KMEM_VMEMUSED, /* Currently alloc'd vmem bytes */
|
CTL_KMEM_VMEMUSED, /* Currently alloc'd vmem bytes */
|
||||||
CTL_KMEM_VMEMMAX, /* Max alloc'd by vmem bytes */
|
CTL_KMEM_VMEMMAX, /* Max alloc'd by vmem bytes */
|
||||||
|
CTL_KMEM_ALLOC_FAILED, /* Cache allocation failed */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CTL_MUTEX_STATS, /* Global mutex statistics */
|
CTL_MUTEX_STATS, /* Global mutex statistics */
|
||||||
|
@ -660,6 +661,14 @@ static struct ctl_table spl_kmem_table[] = {
|
||||||
.mode = 0444,
|
.mode = 0444,
|
||||||
.proc_handler = &proc_doulongvec_minmax,
|
.proc_handler = &proc_doulongvec_minmax,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.ctl_name = CTL_KMEM_ALLOC_FAILED,
|
||||||
|
.procname = "kmem_alloc_failed",
|
||||||
|
.data = &kmem_cache_alloc_failed,
|
||||||
|
.maxlen = sizeof(atomic64_t),
|
||||||
|
.mode = 0444,
|
||||||
|
.proc_handler = &proc_doatomic64,
|
||||||
|
},
|
||||||
{0},
|
{0},
|
||||||
};
|
};
|
||||||
#endif /* DEBUG_KMEM */
|
#endif /* DEBUG_KMEM */
|
||||||
|
|
Loading…
Reference in New Issue