changeset 13682:e7836650181b

1618 zfs causing system to hang in vmem_xalloc() Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Matt Ahrens <matt@delphix.com> Reviewed by: Richard Elling <richard.elling@richardelling.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Steve Gonczi <gonczi@comcast.net> Approved by: Gordon Ross <gwr@nexenta.com>
author George Wilson <gwilson@delphix.com>
date Sun, 06 May 2012 18:49:02 -0700
parents 73253247f9e5
children cf6fa37148dd
files usr/src/lib/libzpool/common/kernel.c usr/src/lib/libzpool/common/sys/zfs_context.h usr/src/uts/common/fs/zfs/arc.c usr/src/uts/common/os/vmem.c usr/src/uts/common/sys/vmem.h
diffstat 5 files changed, 53 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libzpool/common/kernel.c	Thu May 03 15:56:05 2012 +0200
+++ b/usr/src/lib/libzpool/common/kernel.c	Sun May 06 18:49:02 2012 -0700
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <assert.h>
@@ -45,6 +46,7 @@
 uint64_t physmem;
 vnode_t *rootdir = (vnode_t *)0xabcd1234;
 char hw_serial[HW_HOSTID_LEN];
+vmem_t *zio_arena = NULL;
 
 struct utsname utsname = {
 	"userland", "libzpool", "1", "1", "na"
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h	Thu May 03 15:56:05 2012 +0200
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h	Sun May 06 18:49:02 2012 -0700
@@ -20,9 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-/*
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef _SYS_ZFS_CONTEXT_H
@@ -330,9 +329,12 @@
 #define	kmem_debugging()	0
 #define	kmem_cache_reap_now(_c)		/* nothing */
 #define	kmem_cache_set_move(_c, _cb)	/* nothing */
+#define	vmem_qcache_reap(_v)		/* nothing */
 #define	POINTER_INVALIDATE(_pp)		/* nothing */
 #define	POINTER_IS_VALID(_p)	0
 
+extern vmem_t *zio_arena;
+
 typedef umem_cache_t kmem_cache_t;
 
 typedef enum kmem_cbrc {
--- a/usr/src/uts/common/fs/zfs/arc.c	Thu May 03 15:56:05 2012 +0200
+++ b/usr/src/uts/common/fs/zfs/arc.c	Sun May 06 18:49:02 2012 -0700
@@ -21,7 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -1982,6 +1982,11 @@
 		arc_adjust();
 }
 
+/*
+ * Determine if the system is under memory pressure and is asking
+ * to reclaim memory. A return value of 1 indicates that the system
+ * is under memory pressure and that the arc should adjust accordingly.
+ */
 static int
 arc_reclaim_needed(void)
 {
@@ -2029,11 +2034,24 @@
 	 * heap is allocated.  (Or, in the calculation, if less than 1/4th is
 	 * free)
 	 */
-	if (btop(vmem_size(heap_arena, VMEM_FREE)) <
-	    (btop(vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC)) >> 2))
+	if (vmem_size(heap_arena, VMEM_FREE) <
+	    (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2))
 		return (1);
 #endif
 
+	/*
+	 * If zio data pages are being allocated out of a separate heap segment,
+	 * then enforce that the size of available vmem for this arena remains
+	 * above about 1/16th free.
+	 *
+	 * Note: The 1/16th arena free requirement was put in place
+	 * to aggressively evict memory from the arc in order to avoid
+	 * memory fragmentation issues.
+	 */
+	if (zio_arena != NULL &&
+	    vmem_size(zio_arena, VMEM_FREE) <
+	    (vmem_size(zio_arena, VMEM_ALLOC) >> 4))
+		return (1);
 #else
 	if (spa_get_random(100) == 0)
 		return (1);
@@ -2085,6 +2103,13 @@
 	}
 	kmem_cache_reap_now(buf_cache);
 	kmem_cache_reap_now(hdr_cache);
+
+	/*
+	 * Ask the vmem areana to reclaim unused memory from its
+	 * quantum caches.
+	 */
+	if (zio_arena != NULL && strat == ARC_RECLAIM_AGGR)
+		vmem_qcache_reap(zio_arena);
 }
 
 static void
@@ -2218,18 +2243,6 @@
 	if (type == ARC_BUFC_METADATA && arc_meta_used >= arc_meta_limit)
 		return (1);
 
-#ifdef _KERNEL
-	/*
-	 * If zio data pages are being allocated out of a separate heap segment,
-	 * then enforce that the size of available vmem for this area remains
-	 * above about 1/32nd free.
-	 */
-	if (type == ARC_BUFC_DATA && zio_arena != NULL &&
-	    vmem_size(zio_arena, VMEM_FREE) <
-	    (vmem_size(zio_arena, VMEM_ALLOC) >> 5))
-		return (1);
-#endif
-
 	if (arc_reclaim_needed())
 		return (1);
 
--- a/usr/src/uts/common/os/vmem.c	Thu May 03 15:56:05 2012 +0200
+++ b/usr/src/uts/common/os/vmem.c	Sun May 06 18:49:02 2012 -0700
@@ -24,6 +24,10 @@
  */
 
 /*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
  * Big Theory Statement for the virtual memory allocator.
  *
  * For a more complete description of the main ideas, see:
@@ -1706,6 +1710,19 @@
 	(void) timeout(vmem_update, dummy, vmem_update_interval * hz);
 }
 
+void
+vmem_qcache_reap(vmem_t *vmp)
+{
+	int i;
+
+	/*
+	 * Reap any quantum caches that may be part of this vmem.
+	 */
+	for (i = 0; i < VMEM_NQCACHE_MAX; i++)
+		if (vmp->vm_qcache[i])
+			kmem_cache_reap_now(vmp->vm_qcache[i]);
+}
+
 /*
  * Prepare vmem for use.
  */
--- a/usr/src/uts/common/sys/vmem.h	Thu May 03 15:56:05 2012 +0200
+++ b/usr/src/uts/common/sys/vmem.h	Sun May 06 18:49:02 2012 -0700
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef _SYS_VMEM_H
@@ -142,6 +143,7 @@
 extern int vmem_contains(vmem_t *, void *, size_t);
 extern void vmem_walk(vmem_t *, int, void (*)(void *, void *, size_t), void *);
 extern size_t vmem_size(vmem_t *, int);
+extern void vmem_qcache_reap(vmem_t *vmp);
 
 #ifdef	__cplusplus
 }