Re: zonelimit livelock
- From: Gleb Smirnoff <glebius@xxxxxxxxxxx>
- Date: Tue, 29 Aug 2006 13:26:40 +0400
On Mon, Aug 28, 2006 at 06:55:42PM +0200, Peter Holm wrote:
P> While stress testing GENERIC HEAD from Aug 26 13:08 UTC I ran into
P> this livelock:
P>
P> http://people.freebsd.org/~pho/stress/log/cons206.html
Which test leads to this?
btw, I have a patch against that. It isn't perfect, since it
does zone purging synchronously. And Suleiman said, that
the patch didn't help in his case.
--
Totus tuus, Glebius.
GLEBIUS-RIPN GLEB-RIPE
Index: vm/uma.h
===================================================================
RCS file: /home/ncvs/src/sys/vm/uma.h,v
retrieving revision 1.28
diff -u -p -r1.28 uma.h
--- vm/uma.h 8 Oct 2005 21:03:54 -0000 1.28
+++ vm/uma.h 23 May 2006 08:08:08 -0000
@@ -139,6 +139,21 @@ typedef void (*uma_fini)(void *mem, int
*
*/
+/*
+ * Zone low on memory callback
+ *
+ * Arguments:
+ * zone Zone the callback called for.
+ *
+ * Returns:
+ * 0 on failure. UMA subsystem should msleep() awaiting for free memory.
+ * n on success. UMA subsystem should try again to allocate an item.
+ *
+ * Discussion:
+ * This routine is called synchronously from allocation code path,
+ * when zone reaches its maximum number of allocations.
+ */
+typedef int (*uma_mlow)(uma_zone_t zone);
/* Function proto types */
@@ -246,6 +261,15 @@ uma_zone_t uma_zsecond_create(char *name
void uma_zdestroy(uma_zone_t zone);
/*
+ * Drains caches from an uma zone.
+ *
+ * Arguments:
+ * zone The zone we want to drain.
+ *
+ */
+void uma_zdrain(uma_zone_t zone);
+
+/*
* Allocates an item out of a zone
*
* Arguments:
@@ -417,6 +441,18 @@ int uma_zone_set_obj(uma_zone_t zone, st
void uma_zone_set_max(uma_zone_t zone, int nitems);
/*
+ * Sets a callback that would be called when zone is low
+ * on memory.
+ *
+ * Arguments:
+ * zone The zone to work on.
+ *
+ * Returns:
+ * Nothing
+ */
+void uma_zone_set_mlow(uma_zone_t zone, uma_mlow func);
+
+/*
* The following two routines (uma_zone_set_init/fini)
* are used to set the backend init/fini pair which acts on an
* object as it becomes allocated and is placed in a slab within
Index: vm/uma_core.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/uma_core.c,v
retrieving revision 1.139
diff -u -p -r1.139 uma_core.c
--- vm/uma_core.c 18 Jul 2006 01:13:18 -0000 1.139
+++ vm/uma_core.c 2 Aug 2006 12:48:08 -0000
@@ -675,7 +675,6 @@ bucket_cache_drain(uma_zone_t zone)
*
* Arguments:
* zone The zone to free pages from
- * all Should we drain all items?
*
* Returns:
* Nothing.
@@ -767,6 +766,15 @@ finished:
}
/*
+ * Public method for zone_drain().
+ */
+void
+uma_zdrain(uma_zone_t zone)
+{
+ zone_drain(zone);
+}
+
+/*
* Allocate a new slab for a zone. This does not insert the slab onto a list.
*
* Arguments:
@@ -1952,6 +1960,7 @@ uma_zone_slab(uma_zone_t zone, int flags
{
uma_slab_t slab;
uma_keg_t keg;
+ int ntries = 1;
keg = zone->uz_keg;
@@ -2009,9 +2018,13 @@ uma_zone_slab(uma_zone_t zone, int flags
if (flags & M_NOWAIT)
break;
- else
- msleep(keg, &keg->uk_lock, PVM,
- "zonelimit", 0);
+
+ if (ntries && zone->uz_mlow && (*zone->uz_mlow)(zone)) {
+ ntries = 0;
+ continue;
+ }
+
+ msleep(keg, &keg->uk_lock, PVM, "zonelimit", 0);
continue;
}
keg->uk_recurse++;
@@ -2522,6 +2535,15 @@ uma_zone_set_max(uma_zone_t zone, int ni
/* See uma.h */
void
+uma_zone_set_mlow(uma_zone_t zone, uma_mlow func)
+{
+ ZONE_LOCK(zone);
+ zone->uz_mlow = func;
+ ZONE_UNLOCK(zone);
+}
+
+/* See uma.h */
+void
uma_zone_set_init(uma_zone_t zone, uma_init uminit)
{
ZONE_LOCK(zone);
Index: vm/uma_int.h
===================================================================
RCS file: /home/ncvs/src/sys/vm/uma_int.h,v
retrieving revision 1.37
diff -u -p -r1.37 uma_int.h
--- vm/uma_int.h 4 Aug 2005 10:03:53 -0000 1.37
+++ vm/uma_int.h 23 May 2006 08:08:20 -0000
@@ -301,6 +301,7 @@ struct uma_zone {
uma_dtor uz_dtor; /* Destructor */
uma_init uz_init; /* Initializer for each item */
uma_fini uz_fini; /* Discards memory */
+ uma_mlow uz_mlow; /* Called when zone is low on memory */
u_int64_t uz_allocs; /* Total number of allocations */
u_int64_t uz_frees; /* Total number of frees */
Index: kern/kern_mbuf.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_mbuf.c,v
retrieving revision 1.25
diff -u -p -r1.25 kern_mbuf.c
--- kern/kern_mbuf.c 10 Jun 2006 14:34:07 -0000 1.25
+++ kern/kern_mbuf.c 16 Aug 2006 17:41:37 -0000
@@ -164,6 +164,7 @@ static void mb_dtor_pack(void *, int, vo
static int mb_zinit_pack(void *, int, int);
static void mb_zfini_pack(void *, int);
static int mt_zinit_vlan(void *, int, int);
+static int mb_zonelow_clust(uma_zone_t);
static void mb_reclaim(void *);
static void mbuf_init(void *);
@@ -199,8 +200,10 @@ mbuf_init(void *dummy)
NULL, NULL,
#endif
UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
- if (nmbclusters > 0)
+ if (nmbclusters > 0) {
uma_zone_set_max(zone_clust, nmbclusters);
+ uma_zone_set_mlow(zone_clust, mb_zonelow_clust);
+ }
zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack,
mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf);
@@ -450,6 +453,18 @@ mb_dtor_clust(void *mem, int size, void
}
/*
+ * The Mbuf Cluster low on memory callback.
+ */
+static int
+mb_zonelow_clust(uma_zone_t zone)
+{
+
+ KASSERT(zone == zone_clust, ("%s called on uknown zone", __func__));
+ uma_zdrain(zone_pack);
+ return (1);
+}
+
+/*
* The Packet secondary zone's init routine, executed on the
* object's transition from mbuf keg slab to zone cache.
*/
_______________________________________________
freebsd-current@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscribe@xxxxxxxxxxx"
- Follow-Ups:
- Re: zonelimit livelock
- From: Peter Holm
- Re: zonelimit livelock
- References:
- zonelimit livelock
- From: Peter Holm
- zonelimit livelock
- Prev by Date: Re: Panic (in firewall while doing lots of ifconfigs)
- Next by Date: Re: zonelimit livelock
- Previous by thread: Re: zonelimit livelock
- Next by thread: Re: zonelimit livelock
- Index(es):
Relevant Pages
- Re: [PATCH 0/5] make slab gfp fair
... If the boundaries would be fluid then we would not need cpusets. ... ZONE_NORMAL
slab can exhaust memory available for ZONE_DMA. ... Again the question is the watermarks
of which zone? ... ZONE_NORMAL allocation you have 3 to pick from. ... (Linux-Kernel) - Re: Freeze
... >> this code path, the slabzone would get a new slab for each calling thread,
... > They will not flood the system with allocation requests. ... even
if it is for the same zone. ... (freebsd-current) - Re: [PATCH 1/3] vm: kswapd incmin
... > Marcelo Tosatti wrote: ... > controls slab shrinking. ...
> for each zone in node { ... send the line "unsubscribe linux-kernel" in ...
(Linux-Kernel) - [patch 18/67] zone_reclaim: dynamic slab reclaim
... Currently one can enable slab reclaim by setting an explicit option in ... that
means that the slab can grow excessively and that most memory ... This patch implements
slab reclaim during zone reclaim. ... (Linux-Kernel) - Re: [RFC] memory hotremove patch take 2 [02/10] (make page unused)
... it increases the size of struct zone more than yours do and ties these patches to a
part of grouping pages by mobility which you don't do currently. ... +static void ...
(Linux-Kernel)