1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _RCM_IMPL_H
27 #define	_RCM_IMPL_H
28 
29 #ifdef	__cplusplus
30 extern "C" {
31 #endif
32 
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdio_ext.h>
37 #include <stdlib.h>
38 #include <dirent.h>
39 #include <dlfcn.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <limits.h>
43 #include <locale.h>
44 #include <poll.h>
45 #include <signal.h>
46 #include <strings.h>
47 #include <syslog.h>
48 #include <thread.h>
49 #include <unistd.h>
50 #include <sys/mman.h>
51 #include <sys/param.h>
52 #include <sys/stat.h>
53 #include <sys/types.h>
54 #include <librcm.h>
55 #include <librcm_impl.h>
56 
57 #include "rcm_module.h"
58 
59 
60 /*
61  * Daemon states for thread control
62  */
63 #define	RCMD_INIT	1
64 #define	RCMD_NORMAL	2
65 #define	RCMD_CLEANUP	3
66 #define	RCMD_FINI	4
67 
68 /*
69  * flags for node operation
70  */
71 #define	RSRC_NODE_CREATE	1
72 #define	RSRC_NODE_REMOVE	2	/* not used */
73 
74 /*
75  * Resource types
76  */
77 #define	RSRC_TYPE_NORMAL	0
78 #define	RSRC_TYPE_DEVICE	1
79 #define	RSRC_TYPE_FILESYS	2
80 #define	RSRC_TYPE_ABSTRACT	3
81 
82 /*
83  * lock conflict checking flags
84  */
85 #define	LOCK_FOR_DR		0
86 #define	LOCK_FOR_USE		1
87 
88 /*
89  * Sequence number encoding constants
90  */
91 #define	SEQ_NUM_SHIFT	8	/* lowest 8 bits indicate cascade operation */
92 #define	SEQ_NUM_MASK	((1 << SEQ_NUM_SHIFT) - 1)
93 
94 /*
95  * RCM queuing structure
96  */
97 typedef struct rcm_queue {
98 	struct rcm_queue	*next;
99 	struct rcm_queue	*prev;
100 } rcm_queue_t;
101 
102 #define	RCM_STRUCT_BASE_ADDR(struct_type, x, y)		\
103 	((struct_type *) ((void *)(((char *)(x)) -	\
104 			(int)(&((struct_type *)0)->y))))
105 
106 /*
107  * Struct for client loadable module
108  */
109 typedef struct module {
110 	struct module	*next;
111 	void		*dlhandle;
112 	struct rcm_mod_ops *(*init)();
113 	const char	*(*info)();
114 	int		(*fini)();
115 	struct rcm_mod_ops *modops;	/* ops vector */
116 	char		*name;		/* module name */
117 	rcm_handle_t	*rcmhandle;
118 	int		ref_count;
119 	rcm_queue_t	client_q;	/* list of module's clients */
120 	struct script_info *rsi;	/* scripting data */
121 } module_t;
122 
123 /*
124  * Struct for describing a resource client
125  */
126 typedef struct client {
127 	rcm_queue_t	queue;		/* per module queue */
128 	struct client	*next;		/* next client on rsrc node list */
129 	module_t	*module;	/* per-client module */
130 	char		*alias;		/* rsrc_name known to client */
131 	pid_t		pid;		/* pid of regis process */
132 	int		state;		/* rsrc state known to client */
133 	uint_t		flag;		/* flag specified for registration */
134 	uint_t		prv_flags;	/* currently used by rcm scripting */
135 } client_t;
136 
137 /*
138  * defines for client_t:prv_flags (used by rcm scripting)
139  */
140 #define	RCM_NEED_TO_UNREGISTER	1
141 
142 /*
143  * Struct for a list of outstanding rcm requests
144  */
145 typedef struct {
146 	int	n_req;
147 	int	n_req_max;	/* max entries in this block */
148 	struct {
149 		int	seq_num;		/* sequence number of request */
150 		int	state;			/* current state */
151 		id_t	id;			/* id of initiator */
152 		uint_t	flag;			/* request flags */
153 		int	type;			/* resource(device) type */
154 		char	device[MAXPATHLEN];	/* name of device or resource */
155 	} req[1];
156 	/* more entries may follow */
157 } rcm_req_t;
158 
159 /*
160  * struct for describing resource tree node
161  */
162 typedef struct rsrc_node {
163 	struct rsrc_node	*parent;
164 	struct rsrc_node	*sibling;
165 	struct rsrc_node	*child;
166 	char			*name;		/* phys path for devices */
167 	client_t		*users;		/* linked list of users */
168 	int			type;		/* resource type */
169 } rsrc_node_t;
170 
171 /*
172  * struct for tree action args
173  */
174 typedef struct {
175 	int cmd;		/* command */
176 	int seq_num;		/* unique sequence number */
177 	int retcode;		/* return code */
178 	uint_t flag;		/* flag assoc. w command */
179 	timespec_t *interval;	/* for suspend command */
180 	nvlist_t *nvl;		/* for state changes */
181 	rcm_info_t **info;	/* info to be filled in */
182 } tree_walk_arg_t;
183 
184 /*
185  * for synchrizing various threads
186  */
187 typedef struct {
188 	int thr_count;
189 	short wanted;
190 	short state;
191 	time_t last_update;
192 	cond_t cv;
193 	mutex_t lock;
194 } barrier_t;
195 
196 /*
197  * locks
198  */
199 extern mutex_t rcm_req_lock;
200 
201 /*
202  * global variables
203  */
204 extern librcm_ops_t rcm_ops;	/* ops for module callback */
205 extern int need_cleanup;
206 
207 /*
208  * comparison macros
209  *	EQUAL, AFTER, DESCENDENT
210  */
211 #define	EQUAL(x, y)	(strcmp(x, y) == 0)
212 #define	AFTER(x, y)	(strcmp(x, y) > 0)
213 #define	DESCENDENT(x, y)			\
214 	((strlen(x) > strlen(y)) &&		\
215 	(strncmp(x, y, strlen(y)) == 0) &&	\
216 	((x[strlen(y)] == '/') ||		\
217 	(x[strlen(y)] == ':') ||		\
218 	(x[strlen(y) - 1] == '/')))
219 
220 /*
221  * function prototypes
222  */
223 
224 /* top level request handling routines */
225 
226 void event_service(void **, size_t *);
227 int process_resource_suspend(char **, pid_t, uint_t, int, timespec_t *,
228     rcm_info_t **);
229 int notify_resource_resume(char **, pid_t, uint_t, int, rcm_info_t **);
230 int process_resource_offline(char **, pid_t, uint_t, int, rcm_info_t **);
231 int notify_resource_online(char **, pid_t, uint_t, int, rcm_info_t **);
232 int notify_resource_remove(char **, pid_t, uint_t, int, rcm_info_t **);
233 int add_resource_client(char *, char *, pid_t, uint_t, rcm_info_t **);
234 int remove_resource_client(char *, char *, pid_t, uint_t);
235 int get_resource_info(char **, uint_t, int, rcm_info_t **);
236 int notify_resource_event(char *, pid_t, uint_t, int, nvlist_t *,
237     rcm_info_t **);
238 int request_capacity_change(char *, pid_t, uint_t, int, nvlist_t *,
239     rcm_info_t **);
240 int notify_capacity_change(char *, pid_t, uint_t, int, nvlist_t *,
241     rcm_info_t **);
242 int get_resource_state(char *, pid_t, rcm_info_t **);
243 rcm_info_t *rsrc_mod_info();
244 
245 /* dr request list routines */
246 
247 rcm_info_t *rsrc_dr_info();
248 void clean_dr_list();
249 int dr_req_add(char *, pid_t, uint_t, int, int, timespec_t *, rcm_info_t **);
250 int dr_req_update(char *, pid_t, uint_t, int, int, rcm_info_t **);
251 int dr_req_lookup(int, char *);
252 void dr_req_remove(char *, uint_t);
253 int info_req_add(char *, uint_t, int);
254 void info_req_remove(int);
255 int rsrc_check_lock_conflicts(char *, uint_t, int, rcm_info_t **);
256 
257 /* node related routines */
258 
259 int rsrc_get_type(const char *);
260 int rsrc_node_find(char *, int, rsrc_node_t **);
261 int rsrc_node_add_user(rsrc_node_t *, char *, char *, pid_t, uint_t);
262 int rsrc_node_remove_user(rsrc_node_t *, char *, pid_t, uint_t);
263 client_t *rsrc_client_find(char *, pid_t, client_t **);
264 int rsrc_client_action_list(client_t *, int cmd, void *);
265 
266 /* tree related routines */
267 
268 int rsrc_usage_info(char **, uint_t, int, rcm_info_t **);
269 int rsrc_tree_action(rsrc_node_t *, int, tree_walk_arg_t *);
270 
271 /* database helpers and misc */
272 
273 void rcmd_set_state(int);
274 int rcmd_thr_incr(int);
275 void rcmd_thr_decr(void);
276 void rcmd_thr_signal(void);
277 void rcmd_lock_init(void);
278 void rcmd_db_init(void);
279 void rcmd_db_sync(void);
280 void rcmd_db_clean(void);
281 void rcmd_start_timer(int);
282 void rcmd_exit(int);
283 void rcm_log_message(int, char *, ...);
284 void rcm_log_msg(int, char *, ...);
285 void add_busy_rsrc_to_list(char *, pid_t, int, int, char *, const char *,
286 	const char *, nvlist_t *, rcm_info_t **);
287 char *resolve_name(char *);
288 int proc_exist(pid_t);
289 void *s_malloc(size_t);
290 void *s_calloc(int, size_t);
291 void *s_realloc(void *, size_t);
292 char *s_strdup(const char *);
293 
294 /*
295  * RCM queuing function prototypes
296  */
297 void rcm_init_queue(rcm_queue_t *);
298 void rcm_enqueue_head(rcm_queue_t *, rcm_queue_t *);
299 void rcm_enqueue_tail(rcm_queue_t *, rcm_queue_t *);
300 void rcm_enqueue(rcm_queue_t *, rcm_queue_t *);
301 rcm_queue_t *rcm_dequeue_head(rcm_queue_t *);
302 rcm_queue_t *rcm_dequeue_tail(rcm_queue_t *);
303 void rcm_dequeue(rcm_queue_t *);
304 
305 /*
306  * Function protoypes related to rcm scripting
307  */
308 int script_main_init(void);
309 int script_main_fini(void);
310 struct rcm_mod_ops *script_init(module_t *);
311 char *script_info(module_t *);
312 int script_fini(module_t *);
313 
314 
315 #ifdef	__cplusplus
316 }
317 #endif
318 
319 #endif /* _RCM_IMPL_H */
320