From owner-svn-src-head@FreeBSD.ORG Wed Mar 25 08:55:35 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 635C99EB; Wed, 25 Mar 2015 08:55:35 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4E20DB88; Wed, 25 Mar 2015 08:55:35 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2P8tZth038468; Wed, 25 Mar 2015 08:55:35 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2P8tZFp038467; Wed, 25 Mar 2015 08:55:35 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201503250855.t2P8tZFp038467@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Wed, 25 Mar 2015 08:55:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r280495 - head/sys/kern X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 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: Wed, 25 Mar 2015 08:55:35 -0000 Author: hselasky Date: Wed Mar 25 08:55:34 2015 New Revision: 280495 URL: https://svnweb.freebsd.org/changeset/base/280495 Log: Implement a simple OID number garbage collector. Given the increasing number of dynamically created and destroyed SYSCTLs during runtime it is very likely that the current new OID number limit of 0x7fffffff can be reached. Especially if dynamic OID creation and destruction results from automatic tests. Additional changes: - Optimize the typical use case by decrementing the next automatic OID sequence number instead of incrementing it. This saves searching time when inserting new OIDs into a fresh parent OID node. - Add simple check for duplicate non-automatic OID numbers. MFC after: 1 week Modified: head/sys/kern/kern_sysctl.c Modified: head/sys/kern/kern_sysctl.c ============================================================================== --- head/sys/kern/kern_sysctl.c Wed Mar 25 08:23:08 2015 (r280494) +++ head/sys/kern/kern_sysctl.c Wed Mar 25 08:55:34 2015 (r280495) @@ -296,6 +296,8 @@ sysctl_register_oid(struct sysctl_oid *o struct sysctl_oid_list *parent = oidp->oid_parent; struct sysctl_oid *p; struct sysctl_oid *q; + int oid_number; + int timeout = 2; /* * First check if another oid with the same name already @@ -312,37 +314,66 @@ sysctl_register_oid(struct sysctl_oid *o return; } } + /* get current OID number */ + oid_number = oidp->oid_number; + +#if (OID_AUTO >= 0) +#error "OID_AUTO is expected to be a negative value" +#endif /* - * If this oid has a number OID_AUTO, give it a number which - * is greater than any current oid. + * Any negative OID number qualifies as OID_AUTO. Valid OID + * numbers should always be positive. + * * NOTE: DO NOT change the starting value here, change it in * , and make sure it is at least 256 to * accomodate e.g. net.inet.raw as a static sysctl node. */ - if (oidp->oid_number == OID_AUTO) { - static int newoid = CTL_AUTO_START; + if (oid_number < 0) { + static int newoid; + + /* + * By decrementing the next OID number we spend less + * time inserting the OIDs into a sorted list. + */ + if (--newoid < CTL_AUTO_START) + newoid = 0x7fffffff; - oidp->oid_number = newoid++; - if (newoid == 0x7fffffff) - panic("out of oids"); - } -#if 0 - else if (oidp->oid_number >= CTL_AUTO_START) { - /* do not panic; this happens when unregistering sysctl sets */ - printf("static sysctl oid too high: %d", oidp->oid_number); + oid_number = newoid; } -#endif /* - * Insert the oid into the parent's list in order. + * Insert the OID into the parent's list sorted by OID number. */ +retry: q = NULL; SLIST_FOREACH(p, parent, oid_link) { - if (oidp->oid_number < p->oid_number) + /* check if the current OID number is in use */ + if (oid_number == p->oid_number) { + /* get the next valid OID number */ + if (oid_number < CTL_AUTO_START || + oid_number == 0x7fffffff) { + /* wraparound - restart */ + oid_number = CTL_AUTO_START; + /* don't loop forever */ + if (!timeout--) + panic("sysctl: Out of OID numbers\n"); + goto retry; + } else { + oid_number++; + } + } else if (oid_number < p->oid_number) break; q = p; } - if (q) + /* check for non-auto OID number collision */ + if (oidp->oid_number >= 0 && oidp->oid_number < CTL_AUTO_START && + oid_number >= CTL_AUTO_START) { + printf("sysctl: OID number(%d) is already in use for '%s'\n", + oidp->oid_number, oidp->oid_name); + } + /* update the OID number, if any */ + oidp->oid_number = oid_number; + if (q != NULL) SLIST_INSERT_AFTER(q, oidp, oid_link); else SLIST_INSERT_HEAD(parent, oidp, oid_link);