svn commit: r283171 - stable/10/sys/kern

Hans Petter Selasky hselasky at FreeBSD.org
Thu May 21 06:30:45 UTC 2015


Author: hselasky
Date: Thu May 21 06:30:44 2015
New Revision: 283171
URL: https://svnweb.freebsd.org/changeset/base/283171

Log:
  MFC r280495:
  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.

Modified:
  stable/10/sys/kern/kern_sysctl.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/kern_sysctl.c
==============================================================================
--- stable/10/sys/kern/kern_sysctl.c	Thu May 21 05:06:08 2015	(r283170)
+++ stable/10/sys/kern/kern_sysctl.c	Thu May 21 06:30:44 2015	(r283171)
@@ -142,6 +142,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
@@ -158,37 +160,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
 	 * <sys/sysctl.h>, 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);


More information about the svn-src-all mailing list