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