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