xref: /xnu-8792.81.2/bsd/skywalk/core/skywalk_sysctl.c (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1 /*
2  * Copyright (c) 2018-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 #include <skywalk/os_skywalk_private.h>
29 
30 __attribute__((always_inline))
31 static inline struct sysctl_oid *
_skoid_oid_alloc(void)32 _skoid_oid_alloc(void)
33 {
34 	return sk_alloc_type(struct sysctl_oid, Z_WAITOK | Z_NOFAIL, skmem_tag_oid);
35 }
36 
37 __attribute__((always_inline))
38 static inline void
_skoid_oid_free(struct sysctl_oid * oid)39 _skoid_oid_free(struct sysctl_oid *oid)
40 {
41 	sk_free_type(struct sysctl_oid, oid);
42 }
43 
44 __attribute__((always_inline))
45 static inline void
_skoid_oid_init(struct skoid * skoid,struct sysctl_oid * oid,struct sysctl_oid_list * parent,int kind,void * arg1,int arg2,const char * name,int (* handler)SYSCTL_HANDLER_ARGS,const char * fmt)46 _skoid_oid_init(struct skoid *skoid, struct sysctl_oid *oid,
47     struct sysctl_oid_list *parent, int kind, void *arg1, int arg2,
48     const char *name, int (*handler)SYSCTL_HANDLER_ARGS, const char *fmt)
49 {
50 	ASSERT(oid != NULL);
51 	/*
52 	 * Note here we use OID2 for current varsion, which does oid alloc/free
53 	 * ourselves with mcache
54 	 */
55 	oid->oid_link.sle_next = NULL;
56 	oid->oid_parent = parent;
57 	oid->oid_number = OID_AUTO;
58 	oid->oid_kind = CTLFLAG_OID2 | kind;
59 	oid->oid_arg1 = arg1;
60 	oid->oid_arg2 = arg2;
61 	if (&skoid->sko_oid == oid) {
62 		/* for DNODE, store its name inside skoid */
63 		(void) snprintf(skoid->sko_name, sizeof(skoid->sko_name), "%s",
64 		    name);
65 		oid->oid_name = skoid->sko_name;
66 	} else {
67 		/* for leaf property, use static name string */
68 		oid->oid_name = name;
69 	}
70 	oid->oid_handler = handler;
71 	oid->oid_fmt = fmt;
72 	oid->oid_descr = "";    /* unused for current SYSCTL_OID_VERSION */
73 	oid->oid_version = SYSCTL_OID_VERSION;
74 	oid->oid_refcnt = 0;
75 }
76 
77 /*
78  * Create the skoid and register its sysctl_oid.
79  */
80 void
skoid_create(struct skoid * skoid,struct sysctl_oid_list * parent,const char * name,int kind)81 skoid_create(struct skoid *skoid, struct sysctl_oid_list *parent,
82     const char *name, int kind)
83 {
84 	struct sysctl_oid *oid = &skoid->sko_oid;
85 
86 	_skoid_oid_init(skoid, oid, parent,
87 	    CTLTYPE_NODE | CTLFLAG_LOCKED | kind,
88 	    &skoid->sko_oid_list, 0, name, NULL, "N");
89 	sysctl_register_oid(oid);
90 }
91 
92 __attribute__((always_inline))
93 static inline void
_skoid_add_property(struct skoid * skoid,const char * name,int kind,char * fmt,void * arg1,int arg2,int (* handler)SYSCTL_HANDLER_ARGS)94 _skoid_add_property(struct skoid *skoid, const char *name, int kind, char *fmt,
95     void *arg1, int arg2, int (*handler)SYSCTL_HANDLER_ARGS)
96 {
97 	struct sysctl_oid *oid;
98 
99 	oid = _skoid_oid_alloc();
100 	_skoid_oid_init(skoid, oid, &skoid->sko_oid_list, CTLFLAG_LOCKED | kind,
101 	    arg1, arg2, name, handler, fmt);
102 	sysctl_register_oid(oid);
103 }
104 
105 /*
106  * Add int property to skoid.
107  */
108 void
skoid_add_int(struct skoid * skoid,const char * name,int kind,int * int_ptr)109 skoid_add_int(struct skoid *skoid, const char *name, int kind,
110     int *int_ptr)
111 {
112 	_skoid_add_property(skoid, name, CTLTYPE_INT | kind, "I", int_ptr, 0,
113 	    sysctl_handle_int);
114 }
115 
116 /*
117  * Add unsigned int property to skoid.
118  */
119 void
skoid_add_uint(struct skoid * skoid,const char * name,int kind,unsigned int * uint_ptr)120 skoid_add_uint(struct skoid *skoid, const char *name, int kind,
121     unsigned int *uint_ptr)
122 {
123 	_skoid_add_property(skoid, name, CTLTYPE_INT | kind, "IU", uint_ptr, 0,
124 	    sysctl_handle_int);
125 }
126 
127 /*
128  * Add procedure handler property to skoid.
129  */
130 void
skoid_add_handler(struct skoid * skoid,const char * name,int kind,int (* proc)SYSCTL_HANDLER_ARGS,void * proc_arg1,int proc_arg2)131 skoid_add_handler(struct skoid *skoid, const char *name, int kind,
132     int (*proc)SYSCTL_HANDLER_ARGS, void *proc_arg1, int proc_arg2)
133 {
134 	_skoid_add_property(skoid, name, CTLTYPE_INT | kind, "I", proc_arg1,
135 	    proc_arg2, proc);
136 }
137 
138 /*
139  * Destroy skoid and its associated properties
140  *
141  * @discussion This functions only handles properties associated with it and
142  * the unregistration of the sysctl_oid. If skoid itself is dynamically
143  * allocated, it's the caller who should release skoid object.
144  */
145 void
skoid_destroy(struct skoid * skoid)146 skoid_destroy(struct skoid *skoid)
147 {
148 	/*
149 	 * first take down parent sysctl node, which internally deletes it from
150 	 * sko_oid_list, so we don't free it below
151 	 */
152 	sysctl_unregister_oid(&skoid->sko_oid);
153 
154 	/* then destroy all properties sysctl nodes */
155 	struct sysctl_oid *oid, *oid_tmp;
156 	SLIST_FOREACH_SAFE(oid, &skoid->sko_oid_list, oid_link, oid_tmp) {
157 		/* sub dynamic node must be destroyed first */
158 		if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
159 			panic("leaked skoid sub-node detected %p %s",
160 			    oid, oid->oid_name);
161 			__builtin_unreachable();
162 		}
163 		sysctl_unregister_oid(oid);
164 		ASSERT(oid != &skoid->sko_oid);
165 		_skoid_oid_free(oid);
166 	}
167 }
168