xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_smf.c (revision 2a62b4a97f3b5b0ef5f3288ebbfc8509fb793b60)
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 /*
27  * Service Management Facility (SMF) interfaces.
28  */
29 
30 #include <stdio.h>
31 #include <libscf.h>
32 #include <meta.h>
33 
34 static void enable(char *svc_names[], md_error_t *ep);
35 static void disable(char *svc_names[], md_error_t *ep);
36 static int enabled(char *svc_name);
37 static int online(char *svc_names[], char **names);
38 static void wait_online(char *svc_names[]);
39 static int is_online(char *svc_name);
40 
41 static char
42 *svm_core_svcs[] = {
43 	"system/metainit:default",
44 	"system/metasync:default",
45 	"system/mdmonitor:default",
46 	"network/rpc/meta:default",
47 	NULL
48 };
49 
50 static char
51 *svm_diskset_svcs[] = {
52 	"network/rpc/metamed:default",
53 	"network/rpc/metamh:default",
54 	NULL
55 };
56 
57 static char
58 *svm_mn_diskset_svcs[] = {
59 	"network/rpc/mdcomm:default",
60 	NULL
61 };
62 
63 /*
64  * Enable the specified SVM services through the SMF.
65  */
66 int
67 meta_smf_enable(uint_t flags, md_error_t *ep)
68 {
69 	if (flags & META_SMF_CORE) {
70 		enable(svm_core_svcs, ep);
71 		wait_online(svm_core_svcs);
72 	}
73 
74 	if (flags & META_SMF_DISKSET) {
75 		enable(svm_diskset_svcs, ep);
76 		wait_online(svm_diskset_svcs);
77 	}
78 
79 	if (flags & META_SMF_MN_DISKSET) {
80 		enable(svm_mn_diskset_svcs, ep);
81 		wait_online(svm_mn_diskset_svcs);
82 	}
83 
84 	if (ep != NULL)
85 		return ((mdisok(ep)) ? 0 : -1);
86 	else
87 		return (0);
88 }
89 
90 /*
91  * Disable the specified SVM services through the SMF.
92  */
93 int
94 meta_smf_disable(uint_t flags, md_error_t *ep)
95 {
96 	if (flags & META_SMF_CORE) {
97 		disable(svm_core_svcs, ep);
98 	}
99 
100 	if (flags & META_SMF_DISKSET) {
101 		disable(svm_diskset_svcs, ep);
102 	}
103 
104 	if (flags & META_SMF_MN_DISKSET) {
105 		disable(svm_mn_diskset_svcs, ep);
106 	}
107 
108 	if (ep != NULL)
109 		return ((mdisok(ep)) ? 0 : -1);
110 	else
111 		return (0);
112 }
113 
114 /*
115  * Determine if desired services are online.  If all services in the
116  * classes specified by flags are online, 1 is returned.  Otherwise
117  * 0 is returned.
118  */
119 
120 int
121 meta_smf_isonline(uint_t flags, md_error_t *ep)
122 {
123 	int	ret = 1;
124 	char	*names = NULL;
125 
126 	if (flags & META_SMF_CORE) {
127 		if (online(svm_core_svcs, &names) == 0)
128 			ret = 0;
129 	}
130 	if (flags & META_SMF_DISKSET) {
131 		if (online(svm_diskset_svcs, &names) == 0)
132 			ret = 0;
133 	}
134 	if (flags & META_SMF_MN_DISKSET) {
135 		if (online(svm_mn_diskset_svcs, &names) == 0)
136 			ret = 0;
137 	}
138 
139 	if (ret == 0) {
140 		(void) mderror(ep, MDE_SMF_NO_SERVICE, names);
141 		Free(names);
142 	}
143 
144 	return (ret);
145 }
146 
147 /*
148  * Return a bitmask of the META_SMF_* flags indicating which services should be
149  * online given the current SVM configuration.
150  */
151 int
152 meta_smf_getmask()
153 {
154 	int		mask = 0;
155 	mdsetname_t	*sp = NULL;
156 	mddb_config_t	c;
157 	md_error_t	status = mdnullerror;
158 	md_error_t	*ep = &status;
159 	int		max_sets;
160 
161 	/*
162 	 * If there are any local metadbs configured then the core services
163 	 * are needed.
164 	 */
165 	(void) memset(&c, 0, sizeof (c));
166 	c.c_setno = MD_LOCAL_SET;
167 	if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0 || c.c_dbcnt == 0)
168 		return (mask);
169 
170 	mask |= META_SMF_CORE;
171 
172 	/*
173 	 * If any disksets configured then the diskset services are needed.
174 	 * Also check for multi-node sets.
175 	 */
176 	if ((max_sets = get_max_sets(ep)) > 0) {
177 		int i;
178 
179 		mdclrerror(ep);
180 		for (i = 1; i < max_sets; i++) {
181 			md_set_desc	*sd;
182 
183 			if ((sp = metasetnosetname(i, ep)) == NULL) {
184 				if (!mdisok(ep) && !mdiserror(ep, MDE_NO_SET) &&
185 				    !mdiserror(ep, MDE_NOTENOUGH_DB) &&
186 				    !mdiserror(ep, MDE_SMF_NO_SERVICE) &&
187 				    ep->info.errclass != MDEC_RPC) {
188 					/*
189 					 * metad rpc program not registered
190 					 * can't get diskset info
191 					 */
192 					break;
193 				}
194 
195 			} else {
196 				mask |= META_SMF_DISKSET;
197 
198 				if ((sd = metaget_setdesc(sp, ep)) != NULL) {
199 					if (MD_MNSET_DESC(sd)) {
200 						mask |= META_SMF_MN_DISKSET;
201 
202 						/*
203 						 * we don't have to check the
204 						 * rest of the disksets at this
205 						 * point
206 						 */
207 						break;
208 					}
209 				}
210 			}
211 
212 			mdclrerror(ep);
213 		}
214 	}
215 
216 	return (mask);
217 }
218 
219 static void
220 enable(char *svc_names[], md_error_t *ep)
221 {
222 	int i;
223 
224 	for (i = 0; svc_names[i]; i++) {
225 		if (!enabled(svc_names[i]))
226 			if (smf_enable_instance(svc_names[i], 0) != 0) {
227 				if (ep != NULL) {
228 					(void) mderror(ep, MDE_SMF_FAIL,
229 					    svc_names[i]);
230 				}
231 			}
232 	}
233 }
234 
235 static void
236 disable(char *svc_names[], md_error_t *ep)
237 {
238 	int i;
239 
240 	for (i = 0; svc_names[i]; i++) {
241 		if (enabled(svc_names[i]))
242 			if (smf_disable_instance(svc_names[i], 0) != 0) {
243 				if (ep != NULL) {
244 					(void) mderror(ep, MDE_SMF_FAIL,
245 					    svc_names[i]);
246 				}
247 			}
248 	}
249 }
250 
251 static int
252 enabled(char *svc_name)
253 {
254 	scf_simple_prop_t	*prop;
255 	int			rval = 0;
256 
257 	prop = scf_simple_prop_get(NULL, svc_name, SCF_PG_GENERAL,
258 	    SCF_PROPERTY_ENABLED);
259 
260 	if (scf_simple_prop_numvalues(prop) == 1) {
261 		if (*scf_simple_prop_next_boolean(prop) != 0)
262 			rval = 1;
263 	}
264 
265 	scf_simple_prop_free(prop);
266 
267 	return (rval);
268 }
269 
270 /*
271  * There can be a delay while the RPC services get going.  Try to
272  * make sure the RPC daemons are ready to run before we return.
273  * Check 15 times (15 seconds total wait time) and then just
274  * return.
275  */
276 static void
277 wait_online(char *svc_names[])
278 {
279 	int i;
280 	char	*names = NULL;
281 
282 	for (i = 0; i < 15; i++) {
283 		if (online(svc_names, &names))
284 			break;
285 		(void) sleep(1);
286 	}
287 
288 	if (names != NULL)
289 		Free(names);
290 }
291 
292 /*
293  * Check to see if all services in the svc_names are online.  If they are
294  * all online 1 is returned, otherwise 0 is returned.
295  */
296 
297 static int
298 online(char *svc_names[], char **names)
299 {
300 	int i;
301 	int rv = 1;
302 
303 	for (i = 0; svc_names[i]; i++) {
304 		if (is_online(svc_names[i]) == 0) {
305 			int sz;
306 			char *p;
307 
308 			/*
309 			 * Need space for the name, the new line, the
310 			 * tab and the null terminator.
311 			 */
312 			sz = strlen(svc_names[i]) + 3;
313 
314 			if (*names == NULL) {
315 				p = Malloc(sz);
316 				(void) snprintf(p, sz, "\n\t%s", svc_names[i]);
317 
318 			} else {
319 				/* Add space for existing names */
320 				sz += strlen(*names);
321 				p = Malloc(sz);
322 				(void) snprintf(p, sz, "%s\n\t%s", *names,
323 				    svc_names[i]);
324 				Free(*names);
325 			}
326 
327 			*names = p;
328 			rv = 0;
329 		}
330 	}
331 	return (rv);
332 }
333 
334 /*
335  * Return 1 if the specified service is online.  Otherwise, return 0.
336  */
337 static int
338 is_online(char *svc_name)
339 {
340 	int	rval = 0;
341 	char	*s;
342 
343 	if ((s = smf_get_state(svc_name)) != NULL) {
344 		if (strcmp(s, "online") == 0)
345 			rval = 1;
346 		free(s);
347 	}
348 	return (rval);
349 }
350