freebsd-dev/share/man/man9/sysctl_ctx_init.9
Andrzej Bialecki bd3cdc3105 These patches implement dynamic sysctls. It's possible now to add
and remove sysctl oids at will during runtime - they don't rely on
linker sets. Also, the node oids can be referenced by more than
one kernel user, which means that it's possible to create partially
overlapping trees.

Add sysctl contexts to help programmers manage multiple dynamic
oids in convenient way.

Please see the manpages for detailed discussion, and example module
for typical use.

This work is based on ideas and code snippets coming from many
people, among them:  Arun Sharma, Jonathan Lemon, Doug Rabson,
Brian Feldman, Kelly Yancey, Poul-Henning Kamp and others. I'd like
to specially thank Brian Feldman for detailed review and style
fixes.

PR:		kern/16928
Reviewed by:	dfr, green, phk
2000-07-15 10:26:04 +00:00

215 lines
7.2 KiB
Groff

.\"
.\" Copyright (c) 2000, Andrzej Bialecki <abial@freebsd.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd Jul 15, 2000
.Dt sysctl_ctx_init 9
.Os FreeBSD 5.0
.Sh NAME
.Nm sysctl_ctx_init ,
.Nm sysctl_ctx_free ,
.Nm sysctl_ctx_entry_add ,
.Nm sysctl_ctx_entry_find ,
.Nm sysctl_ctx_entry_del ,
.Nd sysctl context for managing dynamically created sysctl oids.
.Sh SYNOPSIS
.Fd #include <sys/sysctl.h>
.Ft int
.Fo sysctl_ctx_init
.Fa "struct sysctl_ctx_list *clist"
.Fc
.Ft int
.Fo sysctl_ctx_free
.Fa "struct sysctl_ctx_list *clist"
.Fc
.Ft struct sysctl_ctx_entry *
.Fo sysctl_ctx_entry_add
.Fa "struct sysctl_ctx_list *clist"
.Fa "struct sysctl_oid *oidp"
.Fc
.Ft struct sysctl_ctx_entry *
.Fo sysctl_ctx_entry_find
.Fa "struct sysctl_ctx_list *clist"
.Fa "struct sysctl_oid *oidp"
.Fc
.Ft int
.Fo sysctl_ctx_entry_del
.Fa "struct sysctl_ctx_list *clist"
.Fa "struct sysctl_oid *oidp"
.Fc
.Sh DESCRIPTION
These functions allow to conveniently manage dynamically created oids.
The sysctl context is responsible for keeping track of created oids,
as well as their proper removal when needed. It adds simple transactional
aspect to oid removal operation, i.e. if the removal operation fails in
the middle, it's possible to rollback the sysctl tree to its previous
state.
.Fn sysctl_ctx_init
initializes context. The
.Va clist
argument must point to already allocated variable. A context MUST be
initialized before use. Once it's initialized, the pointer to the context
can be passed as an argument to all SYSCTL_ADD_* macros, and it will
be updated with entries pointing to newly created oids.
.Pp
Internally the context is represented as TAILQ linked list. The list
consists of
.Pa struct sysctl_ctx_entry
entries:
.Bd -literal -offset indent
struct sysctl_ctx_entry {
struct sysctl_oid *entry;
TAILQ_ENTRY(sysctl_ctx_entry) link;
};
TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
.Ed
.Pp
Each context entry points to one dynamic oid that it manages. Newly
created oids are always inserted in the front of the list.
.Pp
.Fn sysctl_ctx_free
removes the context and the oids it manages. If the function completes
successfuly, all managed oids have been unregistered (removed from the
tree) and freed, together with all their allocated memory, and the
entries of the context have been freed as well.
Removal operation is performed in two steps. First, for each context
entry the function
.Fn sysctl_remove_oid
is executed, with parameter
.Va del
set to 0 (don't free resources, only unregister from the tree).
If there are no errors during this step,
.Fn sysctl_remove_oid
proceeds to the next step. If the first step fails, all unregistered oids
kept in the context are registered again.
(NOTE: in most cases programmer specifies OID_AUTO as oid number
when creating an oid. However, during registration of the oid in
the tree, this number is changed to the first available number
greater than 99. If the first step of context deletion fails,
re-registration of the oid doesn't change the already assigned oid
number (different from OID_AUTO), so that we are sure the re-registered
entries are exactly on the same positions in the tree).
The second step actually preforms deletion of dynamic oids.
.Fn sysctl_remove_oid
goes through the context list, starting from beginning (newest entries).
\fBIMPORTANT:\fR this time the function not only deletes the oids
from the tree, but also frees their memory (if oid_refcnt == 0), as
well as all context entries.
.Pp
The
.Fn sysctl_ctx_entry_add
function allows to add existing dynamic oid to context.
.Pp
The
.Fn sysctl_ctx_entry_del
function removes entry from the context. \fBIMPORTANT:\fR in this
case, only the corresponding
.Pa sysctl_ctx_entry
struct is freed, but
.Pa sysctl_oid *oidp
stays intact.
.Pp
The
.Fn sysctl_ctx_entry_find
function scans through the context list looking for given
.Pa oidp
, and either returns found
.Pa sysctl_ctx_entry
, or NULL.
.Pp
.Pp
.Sh EXAMPLES
The following code example shows how to create new top-level category
and how to hook up another subtree to already existing (static) node,
using contexts to keep track of the oids:
.Bd -literal
#include <sys/sysctl.h>
...
struct sysctl_ctx_list clist;
struct sysctl_oid *oidp;
int a_int;
char *string = "dynamic sysctl";
...
sysctl_ctx_init(&clist);
oidp = SYSCTL_ADD_NODE( &clist, SYSCTL_STATIC_CHILDREN(/* tree top */),
OID_AUTO, newtree, CTFLAG_RW, 0, "new top level tree");
oidp = SYSCTL_ADD_INT( &clist, SYSCTL_CHILDREN(oidp),
OID_AUTO, newint, CTLFLAG_RW, &a_int, 0, "new int leaf");
...
oidp = SYSCTL_ADD_NODE( &clist, SYSCTL_STATIC_CHILDREN(_debug),
OID_AUTO, newtree, CTFLAG_RW, 0, "new tree under debug");
oidp = SYSCTL_ADD_STRING( &clist, SYSCTL_CHILDREN(oidp),
OID_AUTO, newstring, CTLFLAG_R, string, 0, "new string leaf");
...
/* Now we can free up the oids */
if(sysctl_ctx_free(&clist)) {
printf("can't free this context - other oids depend on it");
return(ENOTEMPTY);
} else {
printf("Success!\n"):
return(0);
}
.Ed
.Pp
This example creates the following subtrees:
.Bd -literal -offset indent
debug.newtree.newstring
newtree.newint
.Ed
.Pp
Then both trees are removed and their resources freed through one
.Fn sysctl_ctx_free
call, which starts with freeing the newest entried (leaves) and then
proceeds to free the older entries (in this case the nodes).
.Pp
.Sh SEE ALSO
.Xr sysctl_add_oid 9 ,
.Xr sysctl_remove_oid 9 ,
.Xr sysctl 8 ,
.Xr queue 3
.Sh HISTORY
These functions appeared in
.Fx 5.0 .
.Sh AUTHORS
.An Andrzej Bialecki Aq abial@FreeBSD.org
.Sh BUGS
Currently used removal algorithm is somewhat heavy (in the worst
case all oids need to be unregistered, registered again, and then
unregistered and deleted), but guarantees transactional properties
for removal operation.
All operations on the contexts involve traversing linked lists. For this
reason creation and removal of entries is relatively costly.