Skip to content

Commit

Permalink
1618 zfs causing system to hang in vmem_xalloc()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
George Wilson committed May 7, 2012
1 parent 7660e73 commit 94dd93a
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 17 deletions.
2 changes: 2 additions & 0 deletions usr/src/lib/libzpool/common/kernel.c
Expand Up @@ -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>
Expand All @@ -45,6 +46,7 @@ int aok;
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"
Expand Down
6 changes: 4 additions & 2 deletions usr/src/lib/libzpool/common/sys/zfs_context.h
Expand Up @@ -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
Expand Down Expand Up @@ -330,9 +329,12 @@ extern void kstat_delete(kstat_t *);
#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 {
Expand Down
43 changes: 28 additions & 15 deletions usr/src/uts/common/fs/zfs/arc.c
Expand Up @@ -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.
*/

/*
Expand Down Expand Up @@ -1982,6 +1982,11 @@ arc_shrink(void)
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)
{
Expand Down Expand Up @@ -2029,11 +2034,24 @@ arc_reclaim_needed(void)
* 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);
Expand Down Expand Up @@ -2085,6 +2103,13 @@ arc_kmem_reap_now(arc_reclaim_strategy_t strat)
}
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
Expand Down Expand Up @@ -2218,18 +2243,6 @@ arc_evict_needed(arc_buf_contents_t type)
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);

Expand Down
17 changes: 17 additions & 0 deletions usr/src/uts/common/os/vmem.c
Expand Up @@ -23,6 +23,10 @@
* Use is subject to license terms.
*/

/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/

/*
* Big Theory Statement for the virtual memory allocator.
*
Expand Down Expand Up @@ -1706,6 +1710,19 @@ vmem_update(void *dummy)
(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.
*/
Expand Down
2 changes: 2 additions & 0 deletions usr/src/uts/common/sys/vmem.h
Expand Up @@ -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
Expand Down Expand Up @@ -142,6 +143,7 @@ extern void *vmem_add(vmem_t *, void *, size_t, int);
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
}
Expand Down

0 comments on commit 94dd93a

Please sign in to comment.