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
This commit is contained in:
parent
cad0b2b158
commit
e09860cab6
@ -296,6 +296,8 @@ sysctl_register_oid(struct sysctl_oid *oidp)
|
||||
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 *oidp)
|
||||
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;
|
||||
|
||||
oidp->oid_number = newoid++;
|
||||
if (newoid == 0x7fffffff)
|
||||
panic("out of oids");
|
||||
/*
|
||||
* By decrementing the next OID number we spend less
|
||||
* time inserting the OIDs into a sorted list.
|
||||
*/
|
||||
if (--newoid < CTL_AUTO_START)
|
||||
newoid = 0x7fffffff;
|
||||
|
||||
oid_number = newoid;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
#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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user