From owner-freebsd-current@FreeBSD.ORG Tue Aug 29 09:26:49 2006 Return-Path: X-Original-To: current@FreeBSD.org Delivered-To: freebsd-current@FreeBSD.ORG Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2DE8C16A4DE for ; Tue, 29 Aug 2006 09:26:49 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from cell.sick.ru (cell.sick.ru [217.72.144.68]) by mx1.FreeBSD.org (Postfix) with ESMTP id 977F243D45 for ; Tue, 29 Aug 2006 09:26:48 +0000 (GMT) (envelope-from glebius@FreeBSD.org) Received: from cell.sick.ru (glebius@localhost [127.0.0.1]) by cell.sick.ru (8.13.4/8.13.3) with ESMTP id k7T9QjXR017531 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 29 Aug 2006 13:26:46 +0400 (MSD) (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by cell.sick.ru (8.13.4/8.13.1/Submit) id k7T9Qe8f017530; Tue, 29 Aug 2006 13:26:40 +0400 (MSD) (envelope-from glebius@FreeBSD.org) X-Authentication-Warning: cell.sick.ru: glebius set sender to glebius@FreeBSD.org using -f Date: Tue, 29 Aug 2006 13:26:40 +0400 From: Gleb Smirnoff To: Peter Holm Message-ID: <20060829092640.GM76666@FreeBSD.org> References: <20060828165542.GA78024@peter.osted.lan> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Uwl7UQhJk99r8jnw" Content-Disposition: inline In-Reply-To: <20060828165542.GA78024@peter.osted.lan> User-Agent: Mutt/1.5.6i Cc: current@FreeBSD.org Subject: Re: zonelimit livelock X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Aug 2006 09:26:49 -0000 --Uwl7UQhJk99r8jnw Content-Type: text/plain; charset=koi8-r Content-Disposition: inline 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 --Uwl7UQhJk99r8jnw Content-Type: text/plain; charset=koi8-r Content-Disposition: attachment; filename="zone_pack.diff" 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. */ --Uwl7UQhJk99r8jnw--