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