1618 zfs causing system to hang in vmem_xalloc()
Reviewed by: Eric Schrock <
[email protected]>
Reviewed by: Adam Leventhal <
[email protected]>
Reviewed by: Matt Ahrens <
[email protected]>
Reviewed by: Richard Elling <
[email protected]>
Reviewed by: Garrett D'Amore <
[email protected]>
Reviewed by: Steve Gonczi <
[email protected]>
Approved by: Gordon Ross <
[email protected]>
--- 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
}