Date: Tue, 19 May 2009 11:01:11 -0400 (EDT) From: Rick Macklem <rmacklem@uoguelph.ca> To: freebsd-arch@freebsd.org Subject: nfs server resource exhaustion (before it's too late) Message-ID: <Pine.GSO.4.63.0905191058380.13432@muncher.cs.uoguelph.ca>
next in thread | raw e-mail | index | archive | help
In the experimental nfs server (sys/fs/nfsserver), there is a function that, when it returns non-zero, causes the server to reply NFSERR_DELAY to the client so that it will try the RPC again a little later. (Or, for NFSv2 over UDP, which doesn't have NFSERR_DELAY, it simply drops the request and assumes the client will timeout and try it again.) This is intended to avoid the situation where the server cannot m_get/m_getcl/malloc part way through processing a request, due to resource exhaustion. (The malloc case isn't as critical, since I have high water marks set to limit the # of allocations for the various NFSv4 state related structures that are malloc'd.) At this point the function is just a stub: int nfsrv_mallocmget_limit(void) { return (0); } I just took a quick look (I don't know anything about UMA, except that it seems to be used by m_get and m_getcl) and this was what I could think of for doing the above on FreeBSD8. (It wasn't obvious to me if there was a limit set for the various zones used by malloc(), so I didn't include them. int nfsrv_mallocmget_limit(void) { u_int32_t pages, maxpages; uma_zone_get_pagecnts(zone_clust, &pages, &maxpages); if (maxpages != 0 && (pages * 12 / 10) > maxpages) return (1); return (0); } At this point, the only function I could see that would return the above information is sysctl_vm_zone_stats() and it looks like overkill. Also, the function needs to be relatively low overhead, since it is called for every nfs rpc the server gets so I thought this might be ok? /* added to sys/vm/uma_core.c */ void uma_zone_get_pagecnts(uma_zone_t zone, u_int32_t *pages, u_int32_t *maxpages) { uma_keg_t keg; ZONE_LOCK(zone); keg = zone_first_keg(zone); *pages = keg->uk_pages; *maxpages = keg->uk_maxpages; ZONE_UNLOCK(zone); } Does this look reasonable or can anyone suggest a better alternative? Thanks in advance for any suggestions, rick
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.63.0905191058380.13432>