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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <ctype.h> 30 #include <malloc.h> 31 #include <stdio.h> 32 #include <fcntl.h> 33 #include <stdlib.h> 34 #include <errno.h> 35 #include <string.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <sys/param.h> 39 #include <limits.h> 40 #include <meta.h> 41 #include <svm.h> 42 #include <libsvm.h> 43 44 #define MODEBITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) 45 #define ISREG(A) (((A).st_mode & S_IFMT) == S_IFREG) 46 #define DEFAULT_ROOTDIR "/a" 47 48 49 /* 50 * FUNCTION: svm_start 51 * starts SDS/SVM configuration. If root mirroring exists then the 52 * components of the root mirror are returned in svmpp. 53 * 54 * INPUT: mntpnt - root mount point 55 * svmpp - prealloced structure to return components 56 * repl_state_flag - SVM_CONV/SVM_DONT_CONV 57 * 58 * RETURN: 59 * 0 - SUCCESS 60 * !0 - ERROR 61 * if > 0 errno 62 */ 63 64 int 65 svm_start(char *mntpnt, svm_info_t **svmpp, int repl_state_flag) 66 { 67 char *rootdir, *tf; 68 char *mdevnamep = NULL; 69 char system_file[PATH_MAX]; 70 char mdconf[PATH_MAX]; 71 int rval = 0; 72 73 if (mntpnt == NULL) 74 rootdir = DEFAULT_ROOTDIR; 75 else 76 rootdir = mntpnt; 77 78 if ((rval = snprintf(system_file, PATH_MAX, "%s%s", 79 rootdir, SYSTEM_FILE)) < 0) { 80 return (RET_ERROR); 81 } 82 83 if ((rval = snprintf(mdconf, PATH_MAX, "%s%s", 84 rootdir, MD_CONF)) < 0) { 85 return (RET_ERROR); 86 } 87 88 debug_printf("svm_start(): repl_state_flag %s\n", 89 (repl_state_flag == SVM_DONT_CONV) ? "SVM_DONT_CONV": 90 "SVM_CONV"); 91 92 if (copyfile(MD_CONF, MD_CONF_ORIG)) 93 return (RET_ERROR); 94 95 switch (rval = convert_bootlist(system_file, mdconf, &tf)) { 96 case 0: 97 case -1: /* found in etc/system flag */ 98 break; 99 default: /* convert bootlist failed */ 100 debug_printf("svm_start(): convert_bootlist failed." 101 "rval %d\n", rval); 102 goto errout; 103 } 104 105 if (repl_state_flag == SVM_DONT_CONV) { 106 rval = create_in_file_prop(PROP_KEEP_REPL_STATE, tf); 107 if (rval != 0) 108 goto errout; 109 } 110 111 if (is_upgrade_prop(PROP_DEVID_DESTROY)) { 112 rval = create_in_file_prop(PROP_DEVID_DESTROY, tf); 113 /* 114 * For the idempotent behavior reset internal 115 * flag incase we have to return due to errors 116 */ 117 set_upgrade_prop(PROP_DEVID_DESTROY, 0); 118 if (rval != 0) 119 goto errout; 120 } 121 122 123 /* 124 * Since svm_start is called only after svm_check, 125 * we can assume that there is a valid metadb. If the mddb_bootlist 126 * is not found in etc/system, then it must be in md.conf which 127 * we copied to temporary file pointed to by tf 128 */ 129 if (copyfile(tf, MD_CONF)) { 130 debug_printf("svm_start(): copy of %s to %s failed\n", tf, 131 MD_CONF); 132 goto errout; 133 } 134 135 if ((rval = write_xlate_to_mdconf(rootdir)) != 0) { 136 debug_printf("svm_start(): write_xlate_to_mdconf(%s) failed\n", 137 rootdir); 138 goto errout; 139 } 140 141 if ((rval = write_targ_nm_table(rootdir)) != 0) { 142 goto errout; 143 } 144 145 /* run devfsadm to create the devices specified in md.conf */ 146 if ((rval = system("/usr/sbin/devfsadm -r /tmp -p " 147 "/tmp/root/etc/path_to_inst -i md")) != 0) { 148 debug_printf("svm_start(): devfsadm -i md failed: %d\n", rval); 149 goto errout; 150 } 151 152 /* 153 * We have to unload md after the devfsadm run so that when metainit 154 * loads things it gets the right information from md.conf. 155 */ 156 if (rval = svm_stop()) { 157 debug_printf("svm_start(): svm_stop failed.\n"); 158 return (RET_ERROR); 159 } 160 161 if ((rval = system("/usr/sbin/metainit -r")) != 0) { 162 debug_printf("svm_start(): metainit -r failed: %d\n", rval); 163 goto errout; 164 } 165 166 create_diskset_links(); 167 168 if ((rval = system("/usr/sbin/metasync -r")) != 0) { 169 debug_printf("svm_start(): metasync -r failed: %d\n", rval); 170 goto errout; 171 } 172 173 /* 174 * We ignore failures from metadevadm, since it can fail if 175 * miniroot dev_t's don't match target dev_ts. But it still 176 * will update md.conf with device Id information which is 177 * why we are calling it here. 178 */ 179 180 (void) system("/usr/sbin/metadevadm -r"); 181 182 /* 183 * check to see if we have a root metadevice and if so 184 * get its components. 185 */ 186 187 if ((rval = get_rootmetadevice(rootdir, &mdevnamep)) == 0) { 188 if (rval = get_mdcomponents(mdevnamep, svmpp)) { 189 debug_printf("svm_start(): get_mdcomponents(%s,..)" 190 "failed %d\n", mdevnamep, rval); 191 goto errout; 192 } 193 194 } else { 195 rval = 0; /* not a mirrored root */ 196 debug_printf("svm_start(): get_rootmetadevice(%s,..) " 197 "No root mirrors! ", rootdir); 198 } 199 errout: 200 free(mdevnamep); 201 if (rval != 0) { 202 struct stat sbuf; 203 if (stat(MD_CONF_ORIG, &sbuf) == 0) 204 (void) copyfile(MD_CONF_ORIG, MD_CONF); 205 debug_printf("svm_start(): svm_start failed: %d\n", rval); 206 } else { 207 int i; 208 209 if ((*svmpp)->count > 0) { 210 debug_printf("svmpp: "); 211 debug_printf(" root_md: %s", (*svmpp)->root_md); 212 debug_printf(" count: %d", (*svmpp)->count); 213 for (i = 0; i < (*svmpp)->count; i++) { 214 debug_printf(" md_comps[%d]: %s", i, 215 (*svmpp)->md_comps[i]); 216 } 217 debug_printf(" \n"); 218 } else { 219 if ((*svmpp)->count == 0) 220 debug_printf("svm_start(): no mirrored root\n"); 221 } 222 debug_printf("svm_start(): svm_start succeeded.\n"); 223 } 224 return (rval); 225 } 226 227 /* 228 * FUNCTION: copyfile 229 * 230 * INPUT: self descriptive 231 * 232 * RETURN: 233 * RET_SUCCESS 234 * RET_ERROR 235 */ 236 int 237 copyfile(char *from, char *to) 238 { 239 int fromfd, tofd; 240 char buf[1024]; 241 ssize_t rbytes; 242 struct stat fromstat; 243 244 if ((fromfd = open(from, O_RDONLY | O_NDELAY)) < 0) 245 return (RET_ERROR); 246 247 if ((fstat(fromfd, &fromstat) < 0) || ! ISREG(fromstat)) { 248 (void) close(fromfd); 249 return (RET_ERROR); 250 } 251 252 if ((tofd = open(to, O_CREAT | O_WRONLY | O_TRUNC, 253 (fromstat.st_mode & MODEBITS))) < 0) { 254 (void) close(fromfd); 255 return (RET_ERROR); 256 } 257 258 /* 259 * in case the file exists then perm is forced by this chmod 260 */ 261 (void) fchmod(tofd, fromstat.st_mode & MODEBITS); 262 263 for (;;) { 264 rbytes = read(fromfd, buf, sizeof (buf)); 265 /* 266 * no need to check for negative values since the file 267 * has been successfully stat'ed 268 */ 269 if (rbytes == 0) 270 break; 271 if (write(tofd, buf, rbytes) != rbytes) { 272 rbytes = -1; 273 break; 274 } 275 } 276 277 (void) close(fromfd); 278 (void) close(tofd); 279 if (rbytes < 0) { 280 (void) unlink(to); 281 return (RET_ERROR); 282 } 283 return (RET_SUCCESS); 284 } 285