xref: /titanic_41/usr/src/lib/lvm/libsvm/common/start_svm.c (revision 37714ae43602c675f9dc59b070bfdf9fa702872c)
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