From owner-svn-src-head@FreeBSD.ORG Thu May 14 22:01:33 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 31D06106568E; Thu, 14 May 2009 22:01:33 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 049F18FC1B; Thu, 14 May 2009 22:01:33 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n4EM1WpO003828; Thu, 14 May 2009 22:01:32 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4EM1WaA003827; Thu, 14 May 2009 22:01:32 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200905142201.n4EM1WaA003827@svn.freebsd.org> From: John Baldwin Date: Thu, 14 May 2009 22:01:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r192125 - head/sys/kern X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 May 2009 22:01:35 -0000 Author: jhb Date: Thu May 14 22:01:32 2009 New Revision: 192125 URL: http://svn.freebsd.org/changeset/base/192125 Log: - Use a separate sx lock to try to limit the number of concurrent userland sysctl requests to avoid wiring too much user memory. Only grab this lock if the user's old buffer is larger than a page as a tradeoff to allow more concurrency for common small requests. - Just use a shared lock on the sysctl tree for user sysctl requests now. MFC after: 1 week Modified: head/sys/kern/kern_sysctl.c Modified: head/sys/kern/kern_sysctl.c ============================================================================== --- head/sys/kern/kern_sysctl.c Thu May 14 22:01:14 2009 (r192124) +++ head/sys/kern/kern_sysctl.c Thu May 14 22:01:32 2009 (r192125) @@ -77,11 +77,12 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysct * API rather than using the dynamic API. Use of the dynamic API is * strongly encouraged for most code. * - * This lock is also used to serialize userland sysctl requests. Some - * sysctls wire user memory, and serializing the requests limits the - * amount of wired user memory in use. + * The sysctlmemlock is used to limit the amount of user memory wired for + * sysctl requests. This is implemented by serializing any userland + * sysctl requests larger than a single page via an exclusive lock. */ static struct sx sysctllock; +static struct sx sysctlmemlock; #define SYSCTL_SLOCK() sx_slock(&sysctllock) #define SYSCTL_SUNLOCK() sx_sunlock(&sysctllock) @@ -543,6 +544,7 @@ sysctl_register_all(void *arg) { struct sysctl_oid **oidp; + sx_init(&sysctlmemlock, "sysctl mem"); SYSCTL_INIT(); SYSCTL_XLOCK(); SET_FOREACH(oidp, sysctl_set) @@ -1565,7 +1567,7 @@ userland_sysctl(struct thread *td, int * size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval, int flags) { - int error = 0; + int error = 0, memlocked; struct sysctl_req req; bzero(&req, sizeof req); @@ -1605,14 +1607,20 @@ userland_sysctl(struct thread *td, int * if (KTRPOINT(curthread, KTR_SYSCTL)) ktrsysctl(name, namelen); #endif - - SYSCTL_XLOCK(); + + if (req.oldlen > PAGE_SIZE) { + memlocked = 1; + sx_xlock(&sysctlmemlock); + } else + memlocked = 0; CURVNET_SET(TD_TO_VNET(curthread)); for (;;) { req.oldidx = 0; req.newidx = 0; + SYSCTL_SLOCK(); error = sysctl_root(0, name, namelen, &req); + SYSCTL_SUNLOCK(); if (error != EAGAIN) break; uio_yield(); @@ -1622,7 +1630,8 @@ userland_sysctl(struct thread *td, int * if (req.lock == REQ_WIRED && req.validlen > 0) vsunlock(req.oldptr, req.validlen); - SYSCTL_XUNLOCK(); + if (memlocked) + sx_xunlock(&sysctlmemlock); if (error && error != ENOMEM) return (error);