]> git.proxmox.com Git - mirror_spl.git/commitdiff
Stability hack. Under Solaris when KM_SLEEP is set kmem_cache_alloc()
authorbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
Fri, 9 May 2008 21:21:33 +0000 (21:21 +0000)
committerbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
Fri, 9 May 2008 21:21:33 +0000 (21:21 +0000)
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

include/sys/kmem.h
modules/spl/spl-kmem.c
modules/spl/spl-proc.c

index d67e4f2a2711a5c4a29dd4118f7256be47d82e45..1dfc0bf1e31f28601ebae1fc46fd1b52e84ffcdc 100644 (file)
@@ -32,7 +32,9 @@ extern atomic64_t kmem_alloc_used;
 extern unsigned long kmem_alloc_max;
 extern atomic64_t vmem_alloc_used;
 extern unsigned long vmem_alloc_max;
+
 extern int kmem_warning_flag;
+extern atomic64_t kmem_cache_alloc_failed;
 
 #define KMEM_HASH_BITS          10
 #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,
         void *priv, void *vmp, int flags);
 
-int
-extern __kmem_cache_destroy(kmem_cache_t *cache);
-
-void
-extern __kmem_reap(void);
+extern int __kmem_cache_destroy(kmem_cache_t *cache);
+extern void *__kmem_cache_alloc(kmem_cache_t *cache, gfp_t flags);
+extern void __kmem_reap(void);
 
 int kmem_init(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) \
         __kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags)
 #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_reap_now(cache)      kmem_cache_shrink(cache)
 #define kmem_reap()                     __kmem_reap()
index 75a421ac73c8e03f93c03a670ab3065eaacf3cae..80c4488b1bdd00582500a17b8560bbc7a6ce4e77 100644 (file)
@@ -16,6 +16,7 @@ unsigned long kmem_alloc_max = 0;
 atomic64_t vmem_alloc_used;
 unsigned long vmem_alloc_max = 0;
 int kmem_warning_flag = 1;
+atomic64_t kmem_cache_alloc_failed;
 
 spinlock_t kmem_lock;
 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_destroy
+#undef kmem_cache_alloc
 
 kmem_cache_t *
 __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);
 
+/* 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
 __kmem_reap(void)
 {
@@ -395,6 +421,8 @@ kmem_init(void)
 
                 for (i = 0; i < VMEM_TABLE_SIZE; i++)
                         INIT_HLIST_HEAD(&vmem_table[i]);
+
+               atomic64_set(&kmem_cache_alloc_failed, 0);
         }
 #endif
        RETURN(0);
index 07e18102aefc96bb12dbb24bbf3445f3b13944d8..a8d3485a6a424f1e48c134852dac2d1a2a21f584 100644 (file)
@@ -60,6 +60,7 @@ enum {
         CTL_KMEM_KMEMMAX,         /* Max alloc'd by kmem bytes */
         CTL_KMEM_VMEMUSED,        /* Currently alloc'd vmem bytes */
         CTL_KMEM_VMEMMAX,         /* Max alloc'd by vmem bytes */
+       CTL_KMEM_ALLOC_FAILED,    /* Cache allocation failed */
 #endif
 
        CTL_MUTEX_STATS,          /* Global mutex statistics */
@@ -660,6 +661,14 @@ static struct ctl_table spl_kmem_table[] = {
                 .mode     = 0444,
                 .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},
 };
 #endif /* DEBUG_KMEM */