xref: /onnv-gate/usr/src/cmd/avs/sv/svadm.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #include <sys/types.h>
27*7836SJohn.Forte@Sun.COM #include <sys/stat.h>
28*7836SJohn.Forte@Sun.COM #include <sys/mkdev.h>
29*7836SJohn.Forte@Sun.COM #include <sys/param.h>
30*7836SJohn.Forte@Sun.COM #include <sys/wait.h>
31*7836SJohn.Forte@Sun.COM #include <fcntl.h>
32*7836SJohn.Forte@Sun.COM #include <stdarg.h>
33*7836SJohn.Forte@Sun.COM #include <stdlib.h>
34*7836SJohn.Forte@Sun.COM #include <strings.h>
35*7836SJohn.Forte@Sun.COM #include <errno.h>
36*7836SJohn.Forte@Sun.COM #include <stdio.h>
37*7836SJohn.Forte@Sun.COM #include <locale.h>
38*7836SJohn.Forte@Sun.COM #include <unistd.h>
39*7836SJohn.Forte@Sun.COM #include <search.h>
40*7836SJohn.Forte@Sun.COM #include <libgen.h>
41*7836SJohn.Forte@Sun.COM #include <nsctl.h>
42*7836SJohn.Forte@Sun.COM 
43*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
44*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_u.h>
45*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
46*7836SJohn.Forte@Sun.COM 
47*7836SJohn.Forte@Sun.COM #include <sys/nsctl/sv.h>
48*7836SJohn.Forte@Sun.COM #include <sys/nsctl/sv_impl.h>
49*7836SJohn.Forte@Sun.COM 
50*7836SJohn.Forte@Sun.COM #include <sys/nsctl/cfg.h>
51*7836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_hash.h>
52*7836SJohn.Forte@Sun.COM 
53*7836SJohn.Forte@Sun.COM #include "../sv/svadm.h"
54*7836SJohn.Forte@Sun.COM 
55*7836SJohn.Forte@Sun.COM 
56*7836SJohn.Forte@Sun.COM static int sv_max_devices;
57*7836SJohn.Forte@Sun.COM 
58*7836SJohn.Forte@Sun.COM 
59*7836SJohn.Forte@Sun.COM /*
60*7836SJohn.Forte@Sun.COM  * support for the special cluster tag "local" to be used with -C in a
61*7836SJohn.Forte@Sun.COM  * cluster for local volumes.
62*7836SJohn.Forte@Sun.COM  */
63*7836SJohn.Forte@Sun.COM 
64*7836SJohn.Forte@Sun.COM #define	SV_LOCAL_TAG	"local"
65*7836SJohn.Forte@Sun.COM 
66*7836SJohn.Forte@Sun.COM static int sv_islocal;
67*7836SJohn.Forte@Sun.COM 
68*7836SJohn.Forte@Sun.COM /*
69*7836SJohn.Forte@Sun.COM  * libcfg access.
70*7836SJohn.Forte@Sun.COM  */
71*7836SJohn.Forte@Sun.COM 
72*7836SJohn.Forte@Sun.COM static CFGFILE *cfg;		/* libcfg file pointer */
73*7836SJohn.Forte@Sun.COM static int cfg_changed;		/* set to 1 if we need to commit changes */
74*7836SJohn.Forte@Sun.COM 
75*7836SJohn.Forte@Sun.COM static char *cfg_cluster_tag;	/* local cluster tag */
76*7836SJohn.Forte@Sun.COM 
77*7836SJohn.Forte@Sun.COM static char *implicit_tag;	/* implicit cluster tag */
78*7836SJohn.Forte@Sun.COM 
79*7836SJohn.Forte@Sun.COM 
80*7836SJohn.Forte@Sun.COM /*
81*7836SJohn.Forte@Sun.COM  * Print width for print_sv() output.
82*7836SJohn.Forte@Sun.COM  */
83*7836SJohn.Forte@Sun.COM 
84*7836SJohn.Forte@Sun.COM #define	STATWIDTH	(SV_MAXPATH / 2)
85*7836SJohn.Forte@Sun.COM 
86*7836SJohn.Forte@Sun.COM /*
87*7836SJohn.Forte@Sun.COM  * Pathnames.
88*7836SJohn.Forte@Sun.COM  */
89*7836SJohn.Forte@Sun.COM 
90*7836SJohn.Forte@Sun.COM static const caddr_t sv_rpath = SV_DEVICE;
91*7836SJohn.Forte@Sun.COM 
92*7836SJohn.Forte@Sun.COM /*
93*7836SJohn.Forte@Sun.COM  * Functions.
94*7836SJohn.Forte@Sun.COM  */
95*7836SJohn.Forte@Sun.COM 
96*7836SJohn.Forte@Sun.COM static int read_config_file(const caddr_t, sv_name_t []);
97*7836SJohn.Forte@Sun.COM static int enable_dev(sv_name_t *);
98*7836SJohn.Forte@Sun.COM static int disable_dev(const caddr_t);
99*7836SJohn.Forte@Sun.COM static void error(spcs_s_info_t *, caddr_t, ...);
100*7836SJohn.Forte@Sun.COM static void create_cfg_hash();
101*7836SJohn.Forte@Sun.COM static int find_in_hash(char *path);
102*7836SJohn.Forte@Sun.COM static void destroy_hashtable();
103*7836SJohn.Forte@Sun.COM static void remove_from_cfgfile(char *path, int setnumber);
104*7836SJohn.Forte@Sun.COM 
105*7836SJohn.Forte@Sun.COM static caddr_t program;
106*7836SJohn.Forte@Sun.COM 
107*7836SJohn.Forte@Sun.COM static void
sv_cfg_open(CFGLOCK mode)108*7836SJohn.Forte@Sun.COM sv_cfg_open(CFGLOCK mode)
109*7836SJohn.Forte@Sun.COM {
110*7836SJohn.Forte@Sun.COM 	if (cfg != NULL)
111*7836SJohn.Forte@Sun.COM 		return;
112*7836SJohn.Forte@Sun.COM 
113*7836SJohn.Forte@Sun.COM 	cfg = cfg_open(NULL);
114*7836SJohn.Forte@Sun.COM 	if (cfg == NULL) {
115*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to access the configuration"));
116*7836SJohn.Forte@Sun.COM 		/* NOTREACHED */
117*7836SJohn.Forte@Sun.COM 	}
118*7836SJohn.Forte@Sun.COM 
119*7836SJohn.Forte@Sun.COM 	if (cfg_cluster_tag && *cfg_cluster_tag) {
120*7836SJohn.Forte@Sun.COM 		cfg_resource(cfg, cfg_cluster_tag);
121*7836SJohn.Forte@Sun.COM 	} else {
122*7836SJohn.Forte@Sun.COM 		cfg_resource(cfg, NULL);
123*7836SJohn.Forte@Sun.COM 	}
124*7836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, mode)) {
125*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to lock the configuration"));
126*7836SJohn.Forte@Sun.COM 		/* NOTREACHED */
127*7836SJohn.Forte@Sun.COM 	}
128*7836SJohn.Forte@Sun.COM }
129*7836SJohn.Forte@Sun.COM 
130*7836SJohn.Forte@Sun.COM 
131*7836SJohn.Forte@Sun.COM static void
sv_cfg_close(void)132*7836SJohn.Forte@Sun.COM sv_cfg_close(void)
133*7836SJohn.Forte@Sun.COM {
134*7836SJohn.Forte@Sun.COM 	if (cfg == NULL)
135*7836SJohn.Forte@Sun.COM 		return;
136*7836SJohn.Forte@Sun.COM 
137*7836SJohn.Forte@Sun.COM 	if (cfg_changed) {
138*7836SJohn.Forte@Sun.COM 		(void) cfg_commit(cfg);
139*7836SJohn.Forte@Sun.COM 		cfg_changed = 0;
140*7836SJohn.Forte@Sun.COM 	}
141*7836SJohn.Forte@Sun.COM 
142*7836SJohn.Forte@Sun.COM 	cfg_close(cfg);
143*7836SJohn.Forte@Sun.COM 	cfg = NULL;
144*7836SJohn.Forte@Sun.COM }
145*7836SJohn.Forte@Sun.COM 
146*7836SJohn.Forte@Sun.COM 
147*7836SJohn.Forte@Sun.COM 
148*7836SJohn.Forte@Sun.COM static void
usage(void)149*7836SJohn.Forte@Sun.COM usage(void)
150*7836SJohn.Forte@Sun.COM {
151*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext("usage:\n"));
152*7836SJohn.Forte@Sun.COM 
153*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext(
154*7836SJohn.Forte@Sun.COM 	    "\t%s -h                                 help\n"), program);
155*7836SJohn.Forte@Sun.COM 
156*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext(
157*7836SJohn.Forte@Sun.COM 	    "\t%s [-C tag]                           display status\n"),
158*7836SJohn.Forte@Sun.COM 	    program);
159*7836SJohn.Forte@Sun.COM 
160*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext(
161*7836SJohn.Forte@Sun.COM 	    "\t%s [-C tag] -i                        display "
162*7836SJohn.Forte@Sun.COM 	    "extended status\n"), program);
163*7836SJohn.Forte@Sun.COM 
164*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext(
165*7836SJohn.Forte@Sun.COM 	    "\t%s [-C tag] -v                        display "
166*7836SJohn.Forte@Sun.COM 	    "version number\n"), program);
167*7836SJohn.Forte@Sun.COM 
168*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext(
169*7836SJohn.Forte@Sun.COM 	    "\t%s [-C tag] -e { -f file | volume }   enable\n"), program);
170*7836SJohn.Forte@Sun.COM 
171*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext(
172*7836SJohn.Forte@Sun.COM 	    "\t%s [-C tag] -d { -f file | volume }   disable\n"), program);
173*7836SJohn.Forte@Sun.COM 
174*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, gettext(
175*7836SJohn.Forte@Sun.COM 	    "\t%s [-C tag] -r { -f file | volume }   reconfigure\n"), program);
176*7836SJohn.Forte@Sun.COM 
177*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
178*7836SJohn.Forte@Sun.COM }
179*7836SJohn.Forte@Sun.COM 
180*7836SJohn.Forte@Sun.COM static void
message(caddr_t prefix,spcs_s_info_t * status,caddr_t string,va_list ap)181*7836SJohn.Forte@Sun.COM message(caddr_t prefix, spcs_s_info_t *status, caddr_t string, va_list ap)
182*7836SJohn.Forte@Sun.COM {
183*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, "%s: %s: ", program, prefix);
184*7836SJohn.Forte@Sun.COM 	(void) vfprintf(stderr, string, ap);
185*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, "\n");
186*7836SJohn.Forte@Sun.COM 
187*7836SJohn.Forte@Sun.COM 	if (status) {
188*7836SJohn.Forte@Sun.COM 		spcs_s_report(*status, stderr);
189*7836SJohn.Forte@Sun.COM 		spcs_s_ufree(status);
190*7836SJohn.Forte@Sun.COM 	}
191*7836SJohn.Forte@Sun.COM }
192*7836SJohn.Forte@Sun.COM 
193*7836SJohn.Forte@Sun.COM 
194*7836SJohn.Forte@Sun.COM static void
error(spcs_s_info_t * status,caddr_t string,...)195*7836SJohn.Forte@Sun.COM error(spcs_s_info_t *status, caddr_t string, ...)
196*7836SJohn.Forte@Sun.COM {
197*7836SJohn.Forte@Sun.COM 	va_list ap;
198*7836SJohn.Forte@Sun.COM 	va_start(ap, string);
199*7836SJohn.Forte@Sun.COM 
200*7836SJohn.Forte@Sun.COM 	message(gettext("error"), status, string, ap);
201*7836SJohn.Forte@Sun.COM 
202*7836SJohn.Forte@Sun.COM 	va_end(ap);
203*7836SJohn.Forte@Sun.COM 
204*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
205*7836SJohn.Forte@Sun.COM 	exit(1);
206*7836SJohn.Forte@Sun.COM }
207*7836SJohn.Forte@Sun.COM 
208*7836SJohn.Forte@Sun.COM 
209*7836SJohn.Forte@Sun.COM static void
warn(spcs_s_info_t * status,caddr_t string,...)210*7836SJohn.Forte@Sun.COM warn(spcs_s_info_t *status, caddr_t string, ...)
211*7836SJohn.Forte@Sun.COM {
212*7836SJohn.Forte@Sun.COM 	va_list ap;
213*7836SJohn.Forte@Sun.COM 	va_start(ap, string);
214*7836SJohn.Forte@Sun.COM 
215*7836SJohn.Forte@Sun.COM 	message(gettext("warning"), status, string, ap);
216*7836SJohn.Forte@Sun.COM 
217*7836SJohn.Forte@Sun.COM 	va_end(ap);
218*7836SJohn.Forte@Sun.COM }
219*7836SJohn.Forte@Sun.COM 
220*7836SJohn.Forte@Sun.COM 
221*7836SJohn.Forte@Sun.COM static void
sv_get_maxdevs(void)222*7836SJohn.Forte@Sun.COM sv_get_maxdevs(void)
223*7836SJohn.Forte@Sun.COM {
224*7836SJohn.Forte@Sun.COM 	sv_name_t svn[1];
225*7836SJohn.Forte@Sun.COM 	sv_list_t svl;
226*7836SJohn.Forte@Sun.COM 	int fd;
227*7836SJohn.Forte@Sun.COM 
228*7836SJohn.Forte@Sun.COM 	if (sv_max_devices > 0)
229*7836SJohn.Forte@Sun.COM 		return;
230*7836SJohn.Forte@Sun.COM 
231*7836SJohn.Forte@Sun.COM 	fd = open(sv_rpath, O_RDONLY);
232*7836SJohn.Forte@Sun.COM 	if (fd < 0)
233*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to open %s: %s"),
234*7836SJohn.Forte@Sun.COM 			sv_rpath, strerror(errno));
235*7836SJohn.Forte@Sun.COM 
236*7836SJohn.Forte@Sun.COM 	bzero(&svl, sizeof (svl));
237*7836SJohn.Forte@Sun.COM 	bzero(&svn[0], sizeof (svn));
238*7836SJohn.Forte@Sun.COM 
239*7836SJohn.Forte@Sun.COM 	svl.svl_names = &svn[0];
240*7836SJohn.Forte@Sun.COM 	svl.svl_error = spcs_s_ucreate();
241*7836SJohn.Forte@Sun.COM 
242*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SVIOC_LIST, &svl) < 0) {
243*7836SJohn.Forte@Sun.COM 		(void) close(fd);
244*7836SJohn.Forte@Sun.COM 		error(&svl.svl_error, gettext("unable to get max devs"));
245*7836SJohn.Forte@Sun.COM 	}
246*7836SJohn.Forte@Sun.COM 
247*7836SJohn.Forte@Sun.COM 	spcs_s_ufree(&svl.svl_error);
248*7836SJohn.Forte@Sun.COM 	sv_max_devices = svl.svl_maxdevs;
249*7836SJohn.Forte@Sun.COM 
250*7836SJohn.Forte@Sun.COM 	(void) close(fd);
251*7836SJohn.Forte@Sun.COM }
252*7836SJohn.Forte@Sun.COM 
253*7836SJohn.Forte@Sun.COM 
254*7836SJohn.Forte@Sun.COM static sv_name_t *
sv_alloc_svnames(void)255*7836SJohn.Forte@Sun.COM sv_alloc_svnames(void)
256*7836SJohn.Forte@Sun.COM {
257*7836SJohn.Forte@Sun.COM 	sv_name_t *svn = NULL;
258*7836SJohn.Forte@Sun.COM 
259*7836SJohn.Forte@Sun.COM 	sv_get_maxdevs();
260*7836SJohn.Forte@Sun.COM 
261*7836SJohn.Forte@Sun.COM 	svn = calloc(sv_max_devices, sizeof (*svn));
262*7836SJohn.Forte@Sun.COM 	if (svn == NULL) {
263*7836SJohn.Forte@Sun.COM 		error(NULL, "unable to allocate %ld bytes of memory",
264*7836SJohn.Forte@Sun.COM 		    sv_max_devices * sizeof (*svn));
265*7836SJohn.Forte@Sun.COM 	}
266*7836SJohn.Forte@Sun.COM 
267*7836SJohn.Forte@Sun.COM 	return (svn);
268*7836SJohn.Forte@Sun.COM }
269*7836SJohn.Forte@Sun.COM 
270*7836SJohn.Forte@Sun.COM 
271*7836SJohn.Forte@Sun.COM static void
sv_check_dgislocal(char * dgname)272*7836SJohn.Forte@Sun.COM sv_check_dgislocal(char *dgname)
273*7836SJohn.Forte@Sun.COM {
274*7836SJohn.Forte@Sun.COM 	char *othernode;
275*7836SJohn.Forte@Sun.COM 	int rc;
276*7836SJohn.Forte@Sun.COM 
277*7836SJohn.Forte@Sun.COM 	/*
278*7836SJohn.Forte@Sun.COM 	 * check where this disk service is mastered
279*7836SJohn.Forte@Sun.COM 	 */
280*7836SJohn.Forte@Sun.COM 
281*7836SJohn.Forte@Sun.COM 	rc = cfg_dgname_islocal(dgname, &othernode);
282*7836SJohn.Forte@Sun.COM 	if (rc < 0) {
283*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to find "
284*7836SJohn.Forte@Sun.COM 		    "disk service, %s: %s"), dgname, strerror(errno));
285*7836SJohn.Forte@Sun.COM 	}
286*7836SJohn.Forte@Sun.COM 
287*7836SJohn.Forte@Sun.COM 	if (rc == 0) {
288*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("disk service, %s, is "
289*7836SJohn.Forte@Sun.COM 		    "active on node \"%s\"\nPlease re-issue "
290*7836SJohn.Forte@Sun.COM 		    "the command on that node"), dgname, othernode);
291*7836SJohn.Forte@Sun.COM 	}
292*7836SJohn.Forte@Sun.COM }
293*7836SJohn.Forte@Sun.COM 
294*7836SJohn.Forte@Sun.COM 
295*7836SJohn.Forte@Sun.COM /*
296*7836SJohn.Forte@Sun.COM  * Carry out cluster based checks for a specified volume, or just
297*7836SJohn.Forte@Sun.COM  * global options.
298*7836SJohn.Forte@Sun.COM  */
299*7836SJohn.Forte@Sun.COM static void
sv_check_cluster(char * path)300*7836SJohn.Forte@Sun.COM sv_check_cluster(char *path)
301*7836SJohn.Forte@Sun.COM {
302*7836SJohn.Forte@Sun.COM 	char dgname[CFG_MAX_BUF];
303*7836SJohn.Forte@Sun.COM 	static int sv_iscluster = -1;	/* set to 1 if running in a cluster */
304*7836SJohn.Forte@Sun.COM 
305*7836SJohn.Forte@Sun.COM 	/*
306*7836SJohn.Forte@Sun.COM 	 * Find out if we are running in a cluster
307*7836SJohn.Forte@Sun.COM 	 */
308*7836SJohn.Forte@Sun.COM 	if (sv_iscluster == -1) {
309*7836SJohn.Forte@Sun.COM 		if ((sv_iscluster = cfg_iscluster()) < 0) {
310*7836SJohn.Forte@Sun.COM 			error(NULL, gettext("unable to ascertain environment"));
311*7836SJohn.Forte@Sun.COM 		}
312*7836SJohn.Forte@Sun.COM 	}
313*7836SJohn.Forte@Sun.COM 
314*7836SJohn.Forte@Sun.COM 	if (!sv_iscluster && cfg_cluster_tag != NULL) {
315*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("-C is not valid when not in a cluster"));
316*7836SJohn.Forte@Sun.COM 	}
317*7836SJohn.Forte@Sun.COM 
318*7836SJohn.Forte@Sun.COM 	if (!sv_iscluster || sv_islocal || path == NULL) {
319*7836SJohn.Forte@Sun.COM 		return;
320*7836SJohn.Forte@Sun.COM 	}
321*7836SJohn.Forte@Sun.COM 
322*7836SJohn.Forte@Sun.COM 
323*7836SJohn.Forte@Sun.COM 	/*
324*7836SJohn.Forte@Sun.COM 	 * Cluster-only checks on pathname
325*7836SJohn.Forte@Sun.COM 	 */
326*7836SJohn.Forte@Sun.COM 	if (cfg_dgname(path, dgname, sizeof (dgname)) == NULL) {
327*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to determine "
328*7836SJohn.Forte@Sun.COM 		    "disk group name for %s"), path);
329*7836SJohn.Forte@Sun.COM 		return;
330*7836SJohn.Forte@Sun.COM 	}
331*7836SJohn.Forte@Sun.COM 
332*7836SJohn.Forte@Sun.COM 	if (cfg_cluster_tag != NULL) {
333*7836SJohn.Forte@Sun.COM 		/*
334*7836SJohn.Forte@Sun.COM 		 * Do dgislocal check now in case path did not contain
335*7836SJohn.Forte@Sun.COM 		 * a dgname.
336*7836SJohn.Forte@Sun.COM 		 *
337*7836SJohn.Forte@Sun.COM 		 * E.g. adding a /dev/did/ device to a disk service.
338*7836SJohn.Forte@Sun.COM 		 */
339*7836SJohn.Forte@Sun.COM 
340*7836SJohn.Forte@Sun.COM 		sv_check_dgislocal(cfg_cluster_tag);
341*7836SJohn.Forte@Sun.COM 	}
342*7836SJohn.Forte@Sun.COM 
343*7836SJohn.Forte@Sun.COM 	if (strcmp(dgname, "") == 0)
344*7836SJohn.Forte@Sun.COM 		return;		/* NULL dgname is valid */
345*7836SJohn.Forte@Sun.COM 
346*7836SJohn.Forte@Sun.COM 	if (cfg_cluster_tag == NULL) {
347*7836SJohn.Forte@Sun.COM 		/*
348*7836SJohn.Forte@Sun.COM 		 * Implicitly set the cluster tag to dgname
349*7836SJohn.Forte@Sun.COM 		 */
350*7836SJohn.Forte@Sun.COM 
351*7836SJohn.Forte@Sun.COM 		sv_check_dgislocal(dgname);
352*7836SJohn.Forte@Sun.COM 
353*7836SJohn.Forte@Sun.COM 		if (implicit_tag) {
354*7836SJohn.Forte@Sun.COM 			free(implicit_tag);
355*7836SJohn.Forte@Sun.COM 			implicit_tag = NULL;
356*7836SJohn.Forte@Sun.COM 		}
357*7836SJohn.Forte@Sun.COM 
358*7836SJohn.Forte@Sun.COM 		implicit_tag = strdup(dgname);
359*7836SJohn.Forte@Sun.COM 		if (implicit_tag == NULL) {
360*7836SJohn.Forte@Sun.COM 			error(NULL,
361*7836SJohn.Forte@Sun.COM 			    gettext("unable to allocate memory "
362*7836SJohn.Forte@Sun.COM 			    "for cluster tag"));
363*7836SJohn.Forte@Sun.COM 		}
364*7836SJohn.Forte@Sun.COM 	} else {
365*7836SJohn.Forte@Sun.COM 		/*
366*7836SJohn.Forte@Sun.COM 		 * Check dgname and cluster tag from -C are the same.
367*7836SJohn.Forte@Sun.COM 		 */
368*7836SJohn.Forte@Sun.COM 
369*7836SJohn.Forte@Sun.COM 		if (strcmp(dgname, cfg_cluster_tag) != 0) {
370*7836SJohn.Forte@Sun.COM 			error(NULL,
371*7836SJohn.Forte@Sun.COM 			    gettext("-C (%s) does not match disk group "
372*7836SJohn.Forte@Sun.COM 			    "name (%s) for %s"), cfg_cluster_tag,
373*7836SJohn.Forte@Sun.COM 			    dgname, path);
374*7836SJohn.Forte@Sun.COM 		}
375*7836SJohn.Forte@Sun.COM 
376*7836SJohn.Forte@Sun.COM 		/*
377*7836SJohn.Forte@Sun.COM 		 * sv_check_dgislocal(cfg_cluster_tag) was called above.
378*7836SJohn.Forte@Sun.COM 		 */
379*7836SJohn.Forte@Sun.COM 	}
380*7836SJohn.Forte@Sun.COM }
381*7836SJohn.Forte@Sun.COM 
382*7836SJohn.Forte@Sun.COM 
383*7836SJohn.Forte@Sun.COM static void
print_version(void)384*7836SJohn.Forte@Sun.COM print_version(void)
385*7836SJohn.Forte@Sun.COM {
386*7836SJohn.Forte@Sun.COM 	sv_version_t svv;
387*7836SJohn.Forte@Sun.COM 	int fd;
388*7836SJohn.Forte@Sun.COM 
389*7836SJohn.Forte@Sun.COM 	bzero(&svv, sizeof (svv));
390*7836SJohn.Forte@Sun.COM 	svv.svv_error = spcs_s_ucreate();
391*7836SJohn.Forte@Sun.COM 
392*7836SJohn.Forte@Sun.COM 	fd = open(sv_rpath, O_RDONLY);
393*7836SJohn.Forte@Sun.COM 	if (fd < 0) {
394*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("unable to open %s: %s"),
395*7836SJohn.Forte@Sun.COM 			sv_rpath, strerror(errno));
396*7836SJohn.Forte@Sun.COM 		return;
397*7836SJohn.Forte@Sun.COM 	}
398*7836SJohn.Forte@Sun.COM 
399*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SVIOC_VERSION, &svv) != 0) {
400*7836SJohn.Forte@Sun.COM 		error(&svv.svv_error,
401*7836SJohn.Forte@Sun.COM 		    gettext("unable to read the version number"));
402*7836SJohn.Forte@Sun.COM 		/* NOTREACHED */
403*7836SJohn.Forte@Sun.COM 	}
404*7836SJohn.Forte@Sun.COM 
405*7836SJohn.Forte@Sun.COM 	spcs_s_ufree(&svv.svv_error);
406*7836SJohn.Forte@Sun.COM #ifdef DEBUG
407*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("Storage Volume version %d.%d.%d.%d\n"),
408*7836SJohn.Forte@Sun.COM 	    svv.svv_major_rev, svv.svv_minor_rev,
409*7836SJohn.Forte@Sun.COM 	    svv.svv_micro_rev, svv.svv_baseline_rev);
410*7836SJohn.Forte@Sun.COM #else
411*7836SJohn.Forte@Sun.COM 	if (svv.svv_micro_rev) {
412*7836SJohn.Forte@Sun.COM 		(void) printf(gettext("Storage Volume version %d.%d.%d\n"),
413*7836SJohn.Forte@Sun.COM 		    svv.svv_major_rev, svv.svv_minor_rev, svv.svv_micro_rev);
414*7836SJohn.Forte@Sun.COM 	} else {
415*7836SJohn.Forte@Sun.COM 		(void) printf(gettext("Storage Volume version %d.%d\n"),
416*7836SJohn.Forte@Sun.COM 		    svv.svv_major_rev, svv.svv_minor_rev);
417*7836SJohn.Forte@Sun.COM 	}
418*7836SJohn.Forte@Sun.COM #endif
419*7836SJohn.Forte@Sun.COM 
420*7836SJohn.Forte@Sun.COM 	(void) close(fd);
421*7836SJohn.Forte@Sun.COM }
422*7836SJohn.Forte@Sun.COM 
423*7836SJohn.Forte@Sun.COM int
main(int argc,char * argv[])424*7836SJohn.Forte@Sun.COM main(int argc, char *argv[])
425*7836SJohn.Forte@Sun.COM {
426*7836SJohn.Forte@Sun.COM 	extern int optind;
427*7836SJohn.Forte@Sun.COM 	extern char *optarg;
428*7836SJohn.Forte@Sun.COM 	char *conf_file = NULL;
429*7836SJohn.Forte@Sun.COM 	int enable, disable, compare, print, version;
430*7836SJohn.Forte@Sun.COM 	int opt, Cflag, fflag, iflag;
431*7836SJohn.Forte@Sun.COM 	int rc;
432*7836SJohn.Forte@Sun.COM 
433*7836SJohn.Forte@Sun.COM 	(void) setlocale(LC_ALL, "");
434*7836SJohn.Forte@Sun.COM 	(void) textdomain("svadm");
435*7836SJohn.Forte@Sun.COM 
436*7836SJohn.Forte@Sun.COM 	program = strdup(basename(argv[0]));
437*7836SJohn.Forte@Sun.COM 
438*7836SJohn.Forte@Sun.COM 	Cflag = fflag = iflag = 0;
439*7836SJohn.Forte@Sun.COM 	compare = enable = disable = version = 0;
440*7836SJohn.Forte@Sun.COM 
441*7836SJohn.Forte@Sun.COM 	print = 1;
442*7836SJohn.Forte@Sun.COM 
443*7836SJohn.Forte@Sun.COM 	while ((opt = getopt(argc, argv, "C:def:hirv")) != EOF) {
444*7836SJohn.Forte@Sun.COM 		switch (opt) {
445*7836SJohn.Forte@Sun.COM 
446*7836SJohn.Forte@Sun.COM 		case 'C':
447*7836SJohn.Forte@Sun.COM 			if (Cflag) {
448*7836SJohn.Forte@Sun.COM 				warn(NULL,
449*7836SJohn.Forte@Sun.COM 				    gettext("-C specified multiple times"));
450*7836SJohn.Forte@Sun.COM 				usage();
451*7836SJohn.Forte@Sun.COM 				exit(2);
452*7836SJohn.Forte@Sun.COM 				/* NOTREACHED */
453*7836SJohn.Forte@Sun.COM 			}
454*7836SJohn.Forte@Sun.COM 
455*7836SJohn.Forte@Sun.COM 			Cflag++;
456*7836SJohn.Forte@Sun.COM 			cfg_cluster_tag = optarg;
457*7836SJohn.Forte@Sun.COM 			break;
458*7836SJohn.Forte@Sun.COM 
459*7836SJohn.Forte@Sun.COM 		case 'e':
460*7836SJohn.Forte@Sun.COM 			print = 0;
461*7836SJohn.Forte@Sun.COM 			enable++;
462*7836SJohn.Forte@Sun.COM 			break;
463*7836SJohn.Forte@Sun.COM 
464*7836SJohn.Forte@Sun.COM 		case 'd':
465*7836SJohn.Forte@Sun.COM 			print = 0;
466*7836SJohn.Forte@Sun.COM 			disable++;
467*7836SJohn.Forte@Sun.COM 			break;
468*7836SJohn.Forte@Sun.COM 
469*7836SJohn.Forte@Sun.COM 		case 'f':
470*7836SJohn.Forte@Sun.COM 			fflag++;
471*7836SJohn.Forte@Sun.COM 			conf_file = optarg;
472*7836SJohn.Forte@Sun.COM 			break;
473*7836SJohn.Forte@Sun.COM 
474*7836SJohn.Forte@Sun.COM 		case 'i':
475*7836SJohn.Forte@Sun.COM 			iflag++;
476*7836SJohn.Forte@Sun.COM 			break;
477*7836SJohn.Forte@Sun.COM 
478*7836SJohn.Forte@Sun.COM 		case 'r':
479*7836SJohn.Forte@Sun.COM 			/* Compare running system with sv.cf */
480*7836SJohn.Forte@Sun.COM 			print = 0;
481*7836SJohn.Forte@Sun.COM 			compare++;
482*7836SJohn.Forte@Sun.COM 			break;
483*7836SJohn.Forte@Sun.COM 
484*7836SJohn.Forte@Sun.COM 		case 'v':
485*7836SJohn.Forte@Sun.COM 			print = 0;
486*7836SJohn.Forte@Sun.COM 			version++;
487*7836SJohn.Forte@Sun.COM 			break;
488*7836SJohn.Forte@Sun.COM 
489*7836SJohn.Forte@Sun.COM 		case 'h':
490*7836SJohn.Forte@Sun.COM 			usage();
491*7836SJohn.Forte@Sun.COM 			exit(0);
492*7836SJohn.Forte@Sun.COM 
493*7836SJohn.Forte@Sun.COM 		default:
494*7836SJohn.Forte@Sun.COM 			usage();
495*7836SJohn.Forte@Sun.COM 			exit(2);
496*7836SJohn.Forte@Sun.COM 			/* NOTREACHED */
497*7836SJohn.Forte@Sun.COM 		}
498*7836SJohn.Forte@Sun.COM 	}
499*7836SJohn.Forte@Sun.COM 
500*7836SJohn.Forte@Sun.COM 
501*7836SJohn.Forte@Sun.COM 	/*
502*7836SJohn.Forte@Sun.COM 	 * Usage checks
503*7836SJohn.Forte@Sun.COM 	 */
504*7836SJohn.Forte@Sun.COM 
505*7836SJohn.Forte@Sun.COM 	if ((enable + disable + compare) > 1) {
506*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("-d, -e and -r are mutually exclusive"));
507*7836SJohn.Forte@Sun.COM 		usage();
508*7836SJohn.Forte@Sun.COM 		exit(2);
509*7836SJohn.Forte@Sun.COM 	}
510*7836SJohn.Forte@Sun.COM 
511*7836SJohn.Forte@Sun.COM 	if (fflag && (print || version)) {
512*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("-f is only valid with -d, -e or -r"));
513*7836SJohn.Forte@Sun.COM 		usage();
514*7836SJohn.Forte@Sun.COM 		exit(2);
515*7836SJohn.Forte@Sun.COM 	}
516*7836SJohn.Forte@Sun.COM 
517*7836SJohn.Forte@Sun.COM 	if (fflag && optind != argc) {
518*7836SJohn.Forte@Sun.COM 		usage();
519*7836SJohn.Forte@Sun.COM 		exit(2);
520*7836SJohn.Forte@Sun.COM 	}
521*7836SJohn.Forte@Sun.COM 
522*7836SJohn.Forte@Sun.COM 	if (print || version) {
523*7836SJohn.Forte@Sun.COM 		/* check for no more args */
524*7836SJohn.Forte@Sun.COM 
525*7836SJohn.Forte@Sun.COM 		if (optind != argc) {
526*7836SJohn.Forte@Sun.COM 			usage();
527*7836SJohn.Forte@Sun.COM 			exit(2);
528*7836SJohn.Forte@Sun.COM 		}
529*7836SJohn.Forte@Sun.COM 	} else {
530*7836SJohn.Forte@Sun.COM 		/* check for inline args */
531*7836SJohn.Forte@Sun.COM 
532*7836SJohn.Forte@Sun.COM 		if (!fflag && (argc - optind) != 1) {
533*7836SJohn.Forte@Sun.COM 			usage();
534*7836SJohn.Forte@Sun.COM 			exit(2);
535*7836SJohn.Forte@Sun.COM 		}
536*7836SJohn.Forte@Sun.COM 	}
537*7836SJohn.Forte@Sun.COM 
538*7836SJohn.Forte@Sun.COM 	if (!print && iflag) {
539*7836SJohn.Forte@Sun.COM 		usage();
540*7836SJohn.Forte@Sun.COM 		exit(2);
541*7836SJohn.Forte@Sun.COM 	}
542*7836SJohn.Forte@Sun.COM 
543*7836SJohn.Forte@Sun.COM 
544*7836SJohn.Forte@Sun.COM 	/*
545*7836SJohn.Forte@Sun.COM 	 * Check for the special cluster tag and convert into the
546*7836SJohn.Forte@Sun.COM 	 * internal representation.
547*7836SJohn.Forte@Sun.COM 	 */
548*7836SJohn.Forte@Sun.COM 
549*7836SJohn.Forte@Sun.COM 	if (cfg_cluster_tag != NULL &&
550*7836SJohn.Forte@Sun.COM 	    strcmp(cfg_cluster_tag, SV_LOCAL_TAG) == 0) {
551*7836SJohn.Forte@Sun.COM 		cfg_cluster_tag = "-";
552*7836SJohn.Forte@Sun.COM 		sv_islocal = 1;
553*7836SJohn.Forte@Sun.COM 	}
554*7836SJohn.Forte@Sun.COM 
555*7836SJohn.Forte@Sun.COM 
556*7836SJohn.Forte@Sun.COM 	/*
557*7836SJohn.Forte@Sun.COM 	 * Process commands
558*7836SJohn.Forte@Sun.COM 	 */
559*7836SJohn.Forte@Sun.COM 
560*7836SJohn.Forte@Sun.COM 	if (optind != argc) {
561*7836SJohn.Forte@Sun.COM 		/* deal with inline volume argument */
562*7836SJohn.Forte@Sun.COM 
563*7836SJohn.Forte@Sun.COM 		rc = 0;
564*7836SJohn.Forte@Sun.COM 		if (enable)
565*7836SJohn.Forte@Sun.COM 			rc = enable_one_sv(argv[optind]);
566*7836SJohn.Forte@Sun.COM 		else if (disable)
567*7836SJohn.Forte@Sun.COM 			rc = disable_one_sv(argv[optind]);
568*7836SJohn.Forte@Sun.COM 		else /* if (compare) */
569*7836SJohn.Forte@Sun.COM 			compare_one_sv(argv[optind]);
570*7836SJohn.Forte@Sun.COM 
571*7836SJohn.Forte@Sun.COM 		if (rc != 0)
572*7836SJohn.Forte@Sun.COM 			return (1);
573*7836SJohn.Forte@Sun.COM 
574*7836SJohn.Forte@Sun.COM 		return (0);
575*7836SJohn.Forte@Sun.COM 	}
576*7836SJohn.Forte@Sun.COM 
577*7836SJohn.Forte@Sun.COM 	rc = 0;
578*7836SJohn.Forte@Sun.COM 	if (enable)
579*7836SJohn.Forte@Sun.COM 		rc = enable_sv(conf_file);
580*7836SJohn.Forte@Sun.COM 	else if (disable)
581*7836SJohn.Forte@Sun.COM 		rc = disable_sv(conf_file);
582*7836SJohn.Forte@Sun.COM 	else if (compare)
583*7836SJohn.Forte@Sun.COM 		compare_sv(conf_file);
584*7836SJohn.Forte@Sun.COM 	else if (print)
585*7836SJohn.Forte@Sun.COM 		print_sv(iflag);
586*7836SJohn.Forte@Sun.COM 	else /* if (version) */
587*7836SJohn.Forte@Sun.COM 		print_version();
588*7836SJohn.Forte@Sun.COM 
589*7836SJohn.Forte@Sun.COM 	if (rc != 0)
590*7836SJohn.Forte@Sun.COM 		return (1);
591*7836SJohn.Forte@Sun.COM 
592*7836SJohn.Forte@Sun.COM 	return (0);
593*7836SJohn.Forte@Sun.COM }
594*7836SJohn.Forte@Sun.COM 
595*7836SJohn.Forte@Sun.COM 
596*7836SJohn.Forte@Sun.COM 
597*7836SJohn.Forte@Sun.COM /* LINT - not static as fwcadm uses it */
598*7836SJohn.Forte@Sun.COM static int
enable_sv(char * conf_file)599*7836SJohn.Forte@Sun.COM enable_sv(char *conf_file)
600*7836SJohn.Forte@Sun.COM {
601*7836SJohn.Forte@Sun.COM 	int index;
602*7836SJohn.Forte@Sun.COM 	sv_name_t *svn;
603*7836SJohn.Forte@Sun.COM 	int cnt;
604*7836SJohn.Forte@Sun.COM 	int rc, ret;
605*7836SJohn.Forte@Sun.COM 
606*7836SJohn.Forte@Sun.COM 	svn = sv_alloc_svnames();
607*7836SJohn.Forte@Sun.COM 
608*7836SJohn.Forte@Sun.COM 	index = read_config_file(conf_file, svn);
609*7836SJohn.Forte@Sun.COM 
610*7836SJohn.Forte@Sun.COM 	rc = ret = 0;
611*7836SJohn.Forte@Sun.COM 
612*7836SJohn.Forte@Sun.COM 	for (cnt = 0; cnt < index; cnt++) {
613*7836SJohn.Forte@Sun.COM 
614*7836SJohn.Forte@Sun.COM 		/*
615*7836SJohn.Forte@Sun.COM 		 * Check for more data.
616*7836SJohn.Forte@Sun.COM 		 */
617*7836SJohn.Forte@Sun.COM 		if (svn[cnt].svn_path[0] == '\0') {
618*7836SJohn.Forte@Sun.COM 			/*
619*7836SJohn.Forte@Sun.COM 			 * This was set when reading sv.conf.  After the last
620*7836SJohn.Forte@Sun.COM 			 * line svn_path was set to \0, so we are finished.
621*7836SJohn.Forte@Sun.COM 			 * We shouldn't get here, but put this in just in
622*7836SJohn.Forte@Sun.COM 			 * case.
623*7836SJohn.Forte@Sun.COM 			 */
624*7836SJohn.Forte@Sun.COM 			break;
625*7836SJohn.Forte@Sun.COM 		}
626*7836SJohn.Forte@Sun.COM 		rc = enable_dev(&svn[cnt]);
627*7836SJohn.Forte@Sun.COM 		if (rc && !ret)
628*7836SJohn.Forte@Sun.COM 			ret = rc;
629*7836SJohn.Forte@Sun.COM 	}
630*7836SJohn.Forte@Sun.COM 
631*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
632*7836SJohn.Forte@Sun.COM 
633*7836SJohn.Forte@Sun.COM 	return (ret);
634*7836SJohn.Forte@Sun.COM }
635*7836SJohn.Forte@Sun.COM 
636*7836SJohn.Forte@Sun.COM 
637*7836SJohn.Forte@Sun.COM /* LINT - not static as fwcadm uses it */
638*7836SJohn.Forte@Sun.COM static int
enable_one_sv(caddr_t path)639*7836SJohn.Forte@Sun.COM enable_one_sv(caddr_t path)
640*7836SJohn.Forte@Sun.COM {
641*7836SJohn.Forte@Sun.COM 	sv_name_t svn;
642*7836SJohn.Forte@Sun.COM 	int rc;
643*7836SJohn.Forte@Sun.COM 
644*7836SJohn.Forte@Sun.COM 	sv_get_maxdevs();
645*7836SJohn.Forte@Sun.COM 
646*7836SJohn.Forte@Sun.COM 	bzero(&svn, sizeof (svn));
647*7836SJohn.Forte@Sun.COM 	(void) strncpy(svn.svn_path, path, sizeof (svn.svn_path));
648*7836SJohn.Forte@Sun.COM 	svn.svn_mode = (NSC_DEVICE | NSC_CACHE);
649*7836SJohn.Forte@Sun.COM 
650*7836SJohn.Forte@Sun.COM 	/* force NULL termination */
651*7836SJohn.Forte@Sun.COM 	svn.svn_path[sizeof (svn.svn_path) - 1] = '\0';
652*7836SJohn.Forte@Sun.COM 
653*7836SJohn.Forte@Sun.COM 	rc = enable_dev(&svn);
654*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
655*7836SJohn.Forte@Sun.COM 
656*7836SJohn.Forte@Sun.COM 	return (rc);
657*7836SJohn.Forte@Sun.COM }
658*7836SJohn.Forte@Sun.COM 
659*7836SJohn.Forte@Sun.COM 
660*7836SJohn.Forte@Sun.COM static int
enable_dev(sv_name_t * svn)661*7836SJohn.Forte@Sun.COM enable_dev(sv_name_t *svn)
662*7836SJohn.Forte@Sun.COM {
663*7836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
664*7836SJohn.Forte@Sun.COM 	struct stat stb;
665*7836SJohn.Forte@Sun.COM 	sv_conf_t svc;
666*7836SJohn.Forte@Sun.COM 	int fd;
667*7836SJohn.Forte@Sun.COM 	int sev;
668*7836SJohn.Forte@Sun.COM 	int rc;
669*7836SJohn.Forte@Sun.COM 	char *lcltag;
670*7836SJohn.Forte@Sun.COM 	char *altname;
671*7836SJohn.Forte@Sun.COM 
672*7836SJohn.Forte@Sun.COM 	sv_check_cluster(svn->svn_path);
673*7836SJohn.Forte@Sun.COM 	sv_cfg_open(CFG_WRLOCK);
674*7836SJohn.Forte@Sun.COM 
675*7836SJohn.Forte@Sun.COM 	bzero(&svc, sizeof (svc));
676*7836SJohn.Forte@Sun.COM 
677*7836SJohn.Forte@Sun.COM 	if (stat(svn->svn_path, &stb) != 0) {
678*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("unable to access %s: %s"),
679*7836SJohn.Forte@Sun.COM 			svn->svn_path, strerror(errno));
680*7836SJohn.Forte@Sun.COM 		return (1);
681*7836SJohn.Forte@Sun.COM 	}
682*7836SJohn.Forte@Sun.COM 
683*7836SJohn.Forte@Sun.COM 	if (!S_ISCHR(stb.st_mode)) {
684*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("%s is not a character device - ignored"),
685*7836SJohn.Forte@Sun.COM 		    svn->svn_path);
686*7836SJohn.Forte@Sun.COM 		return (1);
687*7836SJohn.Forte@Sun.COM 	}
688*7836SJohn.Forte@Sun.COM 
689*7836SJohn.Forte@Sun.COM 	svc.svc_major = major(stb.st_rdev);
690*7836SJohn.Forte@Sun.COM 	svc.svc_minor = minor(stb.st_rdev);
691*7836SJohn.Forte@Sun.COM 	(void) strncpy(svc.svc_path, svn->svn_path, sizeof (svc.svc_path));
692*7836SJohn.Forte@Sun.COM 
693*7836SJohn.Forte@Sun.COM 	fd = open(sv_rpath, O_RDONLY);
694*7836SJohn.Forte@Sun.COM 	if (fd < 0) {
695*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("unable to open %s: %s"),
696*7836SJohn.Forte@Sun.COM 			svn->svn_path, strerror(errno));
697*7836SJohn.Forte@Sun.COM 		return (1);
698*7836SJohn.Forte@Sun.COM 	}
699*7836SJohn.Forte@Sun.COM 
700*7836SJohn.Forte@Sun.COM 	svc.svc_flag = svn->svn_mode;
701*7836SJohn.Forte@Sun.COM 	svc.svc_error = spcs_s_ucreate();
702*7836SJohn.Forte@Sun.COM 
703*7836SJohn.Forte@Sun.COM 	/* first, check for duplicates */
704*7836SJohn.Forte@Sun.COM 	rc = cfg_get_canonical_name(cfg, svn->svn_path, &altname);
705*7836SJohn.Forte@Sun.COM 	if (rc < 0) {
706*7836SJohn.Forte@Sun.COM 		spcs_log("sv", NULL, gettext("Unable to parse config file"));
707*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("Unable to parse config file"));
708*7836SJohn.Forte@Sun.COM 		(void) close(fd);
709*7836SJohn.Forte@Sun.COM 		return (1);
710*7836SJohn.Forte@Sun.COM 	}
711*7836SJohn.Forte@Sun.COM 	if (rc) {
712*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("'%s' has already been configured as "
713*7836SJohn.Forte@Sun.COM 		    "'%s'.  Re-enter command with the latter name."),
714*7836SJohn.Forte@Sun.COM 		    svn->svn_path, altname);
715*7836SJohn.Forte@Sun.COM 	}
716*7836SJohn.Forte@Sun.COM 
717*7836SJohn.Forte@Sun.COM 	/* secondly, try to insert it into the dsvol config */
718*7836SJohn.Forte@Sun.COM 	if (implicit_tag && *implicit_tag) {
719*7836SJohn.Forte@Sun.COM 		lcltag = implicit_tag;
720*7836SJohn.Forte@Sun.COM 	} else if (cfg_cluster_tag && *cfg_cluster_tag) {
721*7836SJohn.Forte@Sun.COM 		lcltag = cfg_cluster_tag;
722*7836SJohn.Forte@Sun.COM 	} else {
723*7836SJohn.Forte@Sun.COM 		lcltag = "-";
724*7836SJohn.Forte@Sun.COM 	}
725*7836SJohn.Forte@Sun.COM 	rc = cfg_add_user(cfg, svn->svn_path, lcltag, "sv");
726*7836SJohn.Forte@Sun.COM 	if (CFG_USER_ERR == rc) {
727*7836SJohn.Forte@Sun.COM 		spcs_log("sv", NULL,
728*7836SJohn.Forte@Sun.COM 		    gettext("%s: unable to put %s into dsvol cfg"),
729*7836SJohn.Forte@Sun.COM 		    program, svn->svn_path);
730*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("unable to put %s into dsvol cfg"),
731*7836SJohn.Forte@Sun.COM 		    svn->svn_path);
732*7836SJohn.Forte@Sun.COM 		(void) close(fd);
733*7836SJohn.Forte@Sun.COM 		return (1);
734*7836SJohn.Forte@Sun.COM 	}
735*7836SJohn.Forte@Sun.COM 	cfg_changed = 1;
736*7836SJohn.Forte@Sun.COM 
737*7836SJohn.Forte@Sun.COM 	if (CFG_USER_OK == rc) {
738*7836SJohn.Forte@Sun.COM 		/* success */
739*7836SJohn.Forte@Sun.COM 		(void) close(fd);
740*7836SJohn.Forte@Sun.COM 		return (0);
741*7836SJohn.Forte@Sun.COM 	}
742*7836SJohn.Forte@Sun.COM 
743*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SVIOC_ENABLE, &svc) < 0) {
744*7836SJohn.Forte@Sun.COM 		if ((CFG_USER_REPEAT == rc) && (SV_EENABLED == errno)) {
745*7836SJohn.Forte@Sun.COM 			/* it's ok -- we were just double-checking */
746*7836SJohn.Forte@Sun.COM 			(void) close(fd);
747*7836SJohn.Forte@Sun.COM 			return (0);
748*7836SJohn.Forte@Sun.COM 		}
749*7836SJohn.Forte@Sun.COM 
750*7836SJohn.Forte@Sun.COM 		spcs_log("sv", &svc.svc_error,
751*7836SJohn.Forte@Sun.COM 		    gettext("%s: unable to enable %s"),
752*7836SJohn.Forte@Sun.COM 		    program, svn->svn_path);
753*7836SJohn.Forte@Sun.COM 
754*7836SJohn.Forte@Sun.COM 		warn(&svc.svc_error, gettext("unable to enable %s"),
755*7836SJohn.Forte@Sun.COM 			svn->svn_path);
756*7836SJohn.Forte@Sun.COM 
757*7836SJohn.Forte@Sun.COM 		/* remove it from dsvol, if we're the ones who put it in */
758*7836SJohn.Forte@Sun.COM 		if (CFG_USER_FIRST == rc) {
759*7836SJohn.Forte@Sun.COM 			(void) cfg_rem_user(cfg, svn->svn_path, lcltag, "sv");
760*7836SJohn.Forte@Sun.COM 		}
761*7836SJohn.Forte@Sun.COM 		(void) close(fd);
762*7836SJohn.Forte@Sun.COM 		return (1);
763*7836SJohn.Forte@Sun.COM 	}
764*7836SJohn.Forte@Sun.COM 
765*7836SJohn.Forte@Sun.COM 	spcs_log("sv", NULL, gettext("%s: enabled %s"),
766*7836SJohn.Forte@Sun.COM 	    program, svn->svn_path);
767*7836SJohn.Forte@Sun.COM 
768*7836SJohn.Forte@Sun.COM 	if (implicit_tag != NULL) {
769*7836SJohn.Forte@Sun.COM #ifdef DEBUG
770*7836SJohn.Forte@Sun.COM 		if (cfg_cluster_tag != NULL) {
771*7836SJohn.Forte@Sun.COM 			error(NULL,
772*7836SJohn.Forte@Sun.COM 			    gettext("enable_dev: -C %s AND implicit_tag %s!"),
773*7836SJohn.Forte@Sun.COM 			    cfg_cluster_tag, implicit_tag);
774*7836SJohn.Forte@Sun.COM 		}
775*7836SJohn.Forte@Sun.COM #endif
776*7836SJohn.Forte@Sun.COM 
777*7836SJohn.Forte@Sun.COM 		(void) snprintf(buf, sizeof (buf), "%s - %s",
778*7836SJohn.Forte@Sun.COM 		    svc.svc_path, implicit_tag);
779*7836SJohn.Forte@Sun.COM 	} else {
780*7836SJohn.Forte@Sun.COM 		(void) strcpy(buf, svc.svc_path);
781*7836SJohn.Forte@Sun.COM 	}
782*7836SJohn.Forte@Sun.COM 
783*7836SJohn.Forte@Sun.COM 	rc = 0;
784*7836SJohn.Forte@Sun.COM 	if (cfg_put_cstring(cfg, "sv", buf, sizeof (buf)) < 0) {
785*7836SJohn.Forte@Sun.COM 		warn(NULL,
786*7836SJohn.Forte@Sun.COM 		    gettext("unable to add %s to configuration storage: %s"),
787*7836SJohn.Forte@Sun.COM 		    svc.svc_path, cfg_error(&sev));
788*7836SJohn.Forte@Sun.COM 		rc = 1;
789*7836SJohn.Forte@Sun.COM 	}
790*7836SJohn.Forte@Sun.COM 
791*7836SJohn.Forte@Sun.COM 	cfg_changed = 1;
792*7836SJohn.Forte@Sun.COM 	spcs_s_ufree(&svc.svc_error);
793*7836SJohn.Forte@Sun.COM 	(void) close(fd);
794*7836SJohn.Forte@Sun.COM 
795*7836SJohn.Forte@Sun.COM 	return (rc);
796*7836SJohn.Forte@Sun.COM }
797*7836SJohn.Forte@Sun.COM 
798*7836SJohn.Forte@Sun.COM 
799*7836SJohn.Forte@Sun.COM /*
800*7836SJohn.Forte@Sun.COM  * This routine parses the config file passed in via conf_file and
801*7836SJohn.Forte@Sun.COM  * stores the data in the svn array.  The return value is the number
802*7836SJohn.Forte@Sun.COM  * of entries read from conf_file.  If an error occurs the error()
803*7836SJohn.Forte@Sun.COM  * routine is called (which exits the program).
804*7836SJohn.Forte@Sun.COM  */
805*7836SJohn.Forte@Sun.COM static int
read_config_file(const caddr_t conf_file,sv_name_t svn[])806*7836SJohn.Forte@Sun.COM read_config_file(const caddr_t conf_file, sv_name_t svn[])
807*7836SJohn.Forte@Sun.COM {
808*7836SJohn.Forte@Sun.COM 	char line[1024], rdev[1024], junk[1024];
809*7836SJohn.Forte@Sun.COM 	struct stat stb;
810*7836SJohn.Forte@Sun.COM 	int lineno;
811*7836SJohn.Forte@Sun.COM 	int cnt, i;
812*7836SJohn.Forte@Sun.COM 	int index = 0;		/* Current location in svn array	*/
813*7836SJohn.Forte@Sun.COM 	sv_name_t *cur_svn;	/* Pointer to svn[index]		*/
814*7836SJohn.Forte@Sun.COM 	FILE *fp;
815*7836SJohn.Forte@Sun.COM 
816*7836SJohn.Forte@Sun.COM 	if (access(conf_file, R_OK) != 0 ||
817*7836SJohn.Forte@Sun.COM 	    stat(conf_file, &stb) != 0 ||
818*7836SJohn.Forte@Sun.COM 	    !S_ISREG(stb.st_mode)) {
819*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("cannot read config file %s"), conf_file);
820*7836SJohn.Forte@Sun.COM 	}
821*7836SJohn.Forte@Sun.COM 
822*7836SJohn.Forte@Sun.COM 	if ((fp = fopen(conf_file, "r")) == NULL) {
823*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to open config file %s: %s"),
824*7836SJohn.Forte@Sun.COM 			conf_file, strerror(errno));
825*7836SJohn.Forte@Sun.COM 	}
826*7836SJohn.Forte@Sun.COM 
827*7836SJohn.Forte@Sun.COM 	lineno = 0;
828*7836SJohn.Forte@Sun.COM 
829*7836SJohn.Forte@Sun.COM 	while (fgets(line, sizeof (line), fp) != NULL) {
830*7836SJohn.Forte@Sun.COM 		lineno++;
831*7836SJohn.Forte@Sun.COM 
832*7836SJohn.Forte@Sun.COM 		i = strlen(line);
833*7836SJohn.Forte@Sun.COM 
834*7836SJohn.Forte@Sun.COM 		if (i < 1)
835*7836SJohn.Forte@Sun.COM 			continue;
836*7836SJohn.Forte@Sun.COM 
837*7836SJohn.Forte@Sun.COM 		if (line[i-1] == '\n')
838*7836SJohn.Forte@Sun.COM 			line[i-1] = '\0';
839*7836SJohn.Forte@Sun.COM 		else if (i == (sizeof (line) - 1)) {
840*7836SJohn.Forte@Sun.COM 			warn(NULL, gettext(
841*7836SJohn.Forte@Sun.COM 		"line %d: line too long -- should be less than %d characters"),
842*7836SJohn.Forte@Sun.COM 				lineno, (sizeof (line) - 1));
843*7836SJohn.Forte@Sun.COM 			warn(NULL, gettext("line %d: ignored"), lineno);
844*7836SJohn.Forte@Sun.COM 		}
845*7836SJohn.Forte@Sun.COM 
846*7836SJohn.Forte@Sun.COM 		/*
847*7836SJohn.Forte@Sun.COM 		 * check for comment line.
848*7836SJohn.Forte@Sun.COM 		 */
849*7836SJohn.Forte@Sun.COM 		if (line[0] == '#')
850*7836SJohn.Forte@Sun.COM 			continue;
851*7836SJohn.Forte@Sun.COM 
852*7836SJohn.Forte@Sun.COM 		cnt = sscanf(line, "%s %s", rdev, junk);
853*7836SJohn.Forte@Sun.COM 
854*7836SJohn.Forte@Sun.COM 		if (cnt != 1 && cnt != 2) {
855*7836SJohn.Forte@Sun.COM 			if (cnt > 0) {
856*7836SJohn.Forte@Sun.COM 				warn(NULL, gettext("line %d: invalid format"),
857*7836SJohn.Forte@Sun.COM 					lineno);
858*7836SJohn.Forte@Sun.COM 				warn(NULL, gettext("line %d: ignored"), lineno);
859*7836SJohn.Forte@Sun.COM 			}
860*7836SJohn.Forte@Sun.COM 			continue;
861*7836SJohn.Forte@Sun.COM 		}
862*7836SJohn.Forte@Sun.COM 
863*7836SJohn.Forte@Sun.COM 		rdev[sizeof (rdev) - 1] = '\0';
864*7836SJohn.Forte@Sun.COM 
865*7836SJohn.Forte@Sun.COM 		cur_svn = &svn[index];  /* For easier reading below */
866*7836SJohn.Forte@Sun.COM 
867*7836SJohn.Forte@Sun.COM 		if (strlen(rdev) >= sizeof (cur_svn->svn_path)) {
868*7836SJohn.Forte@Sun.COM 			warn(NULL, gettext(
869*7836SJohn.Forte@Sun.COM 		"line %d: raw device name (%s) longer than %d characters"),
870*7836SJohn.Forte@Sun.COM 				lineno, rdev,
871*7836SJohn.Forte@Sun.COM 				(sizeof (cur_svn->svn_path) - 1));
872*7836SJohn.Forte@Sun.COM 			warn(NULL, gettext("line %d: ignored"), lineno);
873*7836SJohn.Forte@Sun.COM 			continue;
874*7836SJohn.Forte@Sun.COM 		}
875*7836SJohn.Forte@Sun.COM 
876*7836SJohn.Forte@Sun.COM 		(void) strcpy(cur_svn->svn_path, rdev);
877*7836SJohn.Forte@Sun.COM 		cur_svn->svn_mode = (NSC_DEVICE | NSC_CACHE);
878*7836SJohn.Forte@Sun.COM 
879*7836SJohn.Forte@Sun.COM 		index++;
880*7836SJohn.Forte@Sun.COM 	}
881*7836SJohn.Forte@Sun.COM 
882*7836SJohn.Forte@Sun.COM 	/* Set the last path to NULL */
883*7836SJohn.Forte@Sun.COM 	svn[index].svn_path[0] = '\0';
884*7836SJohn.Forte@Sun.COM 
885*7836SJohn.Forte@Sun.COM 	(void) fclose(fp);
886*7836SJohn.Forte@Sun.COM 
887*7836SJohn.Forte@Sun.COM 	return (index);
888*7836SJohn.Forte@Sun.COM }
889*7836SJohn.Forte@Sun.COM 
890*7836SJohn.Forte@Sun.COM 
891*7836SJohn.Forte@Sun.COM /*
892*7836SJohn.Forte@Sun.COM  * Disable the device from the kernel configuration.
893*7836SJohn.Forte@Sun.COM  *
894*7836SJohn.Forte@Sun.COM  * RETURN:
895*7836SJohn.Forte@Sun.COM  *   0 on success
896*7836SJohn.Forte@Sun.COM  *   non-zero on failure.
897*7836SJohn.Forte@Sun.COM  *
898*7836SJohn.Forte@Sun.COM  * Failures are reported to the user.
899*7836SJohn.Forte@Sun.COM  */
900*7836SJohn.Forte@Sun.COM static int
disable_dev(const caddr_t path)901*7836SJohn.Forte@Sun.COM disable_dev(const caddr_t path)
902*7836SJohn.Forte@Sun.COM {
903*7836SJohn.Forte@Sun.COM 	struct stat stb;
904*7836SJohn.Forte@Sun.COM 	sv_conf_t svc;
905*7836SJohn.Forte@Sun.COM 	int fd;
906*7836SJohn.Forte@Sun.COM 
907*7836SJohn.Forte@Sun.COM 	sv_check_cluster(path);
908*7836SJohn.Forte@Sun.COM 
909*7836SJohn.Forte@Sun.COM 	if (stat(path, &stb) < 0) {
910*7836SJohn.Forte@Sun.COM 		svc.svc_major = (major_t)-1;
911*7836SJohn.Forte@Sun.COM 		svc.svc_minor = (minor_t)-1;
912*7836SJohn.Forte@Sun.COM 	} else {
913*7836SJohn.Forte@Sun.COM 		svc.svc_major = major(stb.st_rdev);
914*7836SJohn.Forte@Sun.COM 		svc.svc_minor = minor(stb.st_rdev);
915*7836SJohn.Forte@Sun.COM 	}
916*7836SJohn.Forte@Sun.COM 
917*7836SJohn.Forte@Sun.COM 	if ((fd = open(sv_rpath, O_RDONLY)) < 0) {
918*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("unable to open %s: %s"),
919*7836SJohn.Forte@Sun.COM 			sv_rpath, strerror(errno));
920*7836SJohn.Forte@Sun.COM 		return (-1);
921*7836SJohn.Forte@Sun.COM 	}
922*7836SJohn.Forte@Sun.COM 
923*7836SJohn.Forte@Sun.COM 	(void) strcpy(svc.svc_path, path);
924*7836SJohn.Forte@Sun.COM 	svc.svc_error = spcs_s_ucreate();
925*7836SJohn.Forte@Sun.COM 
926*7836SJohn.Forte@Sun.COM 	/*
927*7836SJohn.Forte@Sun.COM 	 * Issue the ioctl to attempt to disable this device.  Note that all
928*7836SJohn.Forte@Sun.COM 	 * the libdscfg details are handled elsewhere.
929*7836SJohn.Forte@Sun.COM 	 */
930*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SVIOC_DISABLE, &svc) < 0) {
931*7836SJohn.Forte@Sun.COM 		if (errno != SV_EDISABLED) {
932*7836SJohn.Forte@Sun.COM 			spcs_log("sv", &svc.svc_error,
933*7836SJohn.Forte@Sun.COM 					gettext("%s: unable to disable %s"),
934*7836SJohn.Forte@Sun.COM 					program, path);
935*7836SJohn.Forte@Sun.COM 
936*7836SJohn.Forte@Sun.COM 			warn(&svc.svc_error,
937*7836SJohn.Forte@Sun.COM 					gettext("unable to disable %s"), path);
938*7836SJohn.Forte@Sun.COM 			(void) close(fd);
939*7836SJohn.Forte@Sun.COM 			return (-1);
940*7836SJohn.Forte@Sun.COM 		}
941*7836SJohn.Forte@Sun.COM 	}
942*7836SJohn.Forte@Sun.COM 
943*7836SJohn.Forte@Sun.COM 	spcs_log("sv", NULL, gettext("%s: disabled %s"), program, path);
944*7836SJohn.Forte@Sun.COM 
945*7836SJohn.Forte@Sun.COM 	spcs_s_ufree(&svc.svc_error);
946*7836SJohn.Forte@Sun.COM 	(void) close(fd);
947*7836SJohn.Forte@Sun.COM 
948*7836SJohn.Forte@Sun.COM 	return (0);
949*7836SJohn.Forte@Sun.COM }
950*7836SJohn.Forte@Sun.COM 
951*7836SJohn.Forte@Sun.COM 
952*7836SJohn.Forte@Sun.COM static void
print_cluster_tag(const int setnumber)953*7836SJohn.Forte@Sun.COM print_cluster_tag(const int setnumber)
954*7836SJohn.Forte@Sun.COM {
955*7836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
956*7836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
957*7836SJohn.Forte@Sun.COM 
958*7836SJohn.Forte@Sun.COM 	bzero(buf, sizeof (buf));
959*7836SJohn.Forte@Sun.COM 	(void) snprintf(key, sizeof (key), "sv.set%d.cnode", setnumber);
960*7836SJohn.Forte@Sun.COM 
961*7836SJohn.Forte@Sun.COM 	(void) cfg_get_cstring(cfg, key, buf, sizeof (buf));
962*7836SJohn.Forte@Sun.COM 
963*7836SJohn.Forte@Sun.COM 	if (*buf != '\0') {
964*7836SJohn.Forte@Sun.COM 		if (strcmp(buf, "-") == 0) {
965*7836SJohn.Forte@Sun.COM 			(void) printf(" [%s]", gettext("local to node"));
966*7836SJohn.Forte@Sun.COM 		} else {
967*7836SJohn.Forte@Sun.COM 			(void) printf(" [%s: %s]", gettext("cluster"), buf);
968*7836SJohn.Forte@Sun.COM 		}
969*7836SJohn.Forte@Sun.COM 	}
970*7836SJohn.Forte@Sun.COM }
971*7836SJohn.Forte@Sun.COM 
972*7836SJohn.Forte@Sun.COM 
973*7836SJohn.Forte@Sun.COM /* LINT - not static as fwcadm uses it */
974*7836SJohn.Forte@Sun.COM static void
print_sv(int verbose)975*7836SJohn.Forte@Sun.COM print_sv(int verbose)
976*7836SJohn.Forte@Sun.COM {
977*7836SJohn.Forte@Sun.COM 	sv_name_t *svn, *svn_system;	/* Devices in system */
978*7836SJohn.Forte@Sun.COM 	sv_list_t svl_system;
979*7836SJohn.Forte@Sun.COM 	int fd, i;
980*7836SJohn.Forte@Sun.COM 	int setnumber;
981*7836SJohn.Forte@Sun.COM 
982*7836SJohn.Forte@Sun.COM 	sv_check_cluster(NULL);
983*7836SJohn.Forte@Sun.COM 	sv_cfg_open(CFG_RDLOCK);
984*7836SJohn.Forte@Sun.COM 
985*7836SJohn.Forte@Sun.COM 	svn_system = sv_alloc_svnames();
986*7836SJohn.Forte@Sun.COM 
987*7836SJohn.Forte@Sun.COM 	if ((fd = open(sv_rpath, O_RDONLY)) < 0) {
988*7836SJohn.Forte@Sun.COM 		(void) printf(gettext("unable to open %s: %s"),
989*7836SJohn.Forte@Sun.COM 			sv_rpath, strerror(errno));
990*7836SJohn.Forte@Sun.COM 		return;
991*7836SJohn.Forte@Sun.COM 	}
992*7836SJohn.Forte@Sun.COM 
993*7836SJohn.Forte@Sun.COM 	/* Grab the system list from the driver */
994*7836SJohn.Forte@Sun.COM 	svl_system.svl_count = sv_max_devices;
995*7836SJohn.Forte@Sun.COM 	svl_system.svl_names = &svn_system[0];
996*7836SJohn.Forte@Sun.COM 	svl_system.svl_error = spcs_s_ucreate();
997*7836SJohn.Forte@Sun.COM 
998*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SVIOC_LIST, &svl_system) < 0) {
999*7836SJohn.Forte@Sun.COM 		error(&svl_system.svl_error, gettext("unable to get list"));
1000*7836SJohn.Forte@Sun.COM 	}
1001*7836SJohn.Forte@Sun.COM 
1002*7836SJohn.Forte@Sun.COM 	spcs_s_ufree(&svl_system.svl_error);
1003*7836SJohn.Forte@Sun.COM 	(void) close(fd);
1004*7836SJohn.Forte@Sun.COM 
1005*7836SJohn.Forte@Sun.COM 	/*
1006*7836SJohn.Forte@Sun.COM 	 * We build a hashmap out of the entries from the config file to make
1007*7836SJohn.Forte@Sun.COM 	 * searching faster. We end up taking a performance hit when the # of
1008*7836SJohn.Forte@Sun.COM 	 * volumes is small, but for larger configurations it's a
1009*7836SJohn.Forte@Sun.COM 	 * HUGE improvement.
1010*7836SJohn.Forte@Sun.COM 	 */
1011*7836SJohn.Forte@Sun.COM 
1012*7836SJohn.Forte@Sun.COM 	/* build the hashtable */
1013*7836SJohn.Forte@Sun.COM 	cfg_rewind(cfg, CFG_SEC_CONF);
1014*7836SJohn.Forte@Sun.COM 	create_cfg_hash();
1015*7836SJohn.Forte@Sun.COM 
1016*7836SJohn.Forte@Sun.COM 	/*
1017*7836SJohn.Forte@Sun.COM 	 * For each volume found from the kernel, print out
1018*7836SJohn.Forte@Sun.COM 	 * info about it from the kernel.
1019*7836SJohn.Forte@Sun.COM 	 */
1020*7836SJohn.Forte@Sun.COM 	for (i = 0; i < svl_system.svl_count; i++) {
1021*7836SJohn.Forte@Sun.COM 		if (*svn_system[i].svn_path == '\0') {
1022*7836SJohn.Forte@Sun.COM 			break;
1023*7836SJohn.Forte@Sun.COM 		}
1024*7836SJohn.Forte@Sun.COM 
1025*7836SJohn.Forte@Sun.COM 		svn = &svn_system[i];
1026*7836SJohn.Forte@Sun.COM 		if (svn->svn_mode == 0) {
1027*7836SJohn.Forte@Sun.COM #ifdef DEBUG
1028*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("%s [kernel guard]\n"),
1029*7836SJohn.Forte@Sun.COM 			    svn->svn_path);
1030*7836SJohn.Forte@Sun.COM #endif
1031*7836SJohn.Forte@Sun.COM 			continue;
1032*7836SJohn.Forte@Sun.COM 		}
1033*7836SJohn.Forte@Sun.COM 		/* get sv entry from the hashtable */
1034*7836SJohn.Forte@Sun.COM 		if ((setnumber = find_in_hash(svn->svn_path)) != -1) {
1035*7836SJohn.Forte@Sun.COM 			(void) printf("%-*s", STATWIDTH, svn->svn_path);
1036*7836SJohn.Forte@Sun.COM 
1037*7836SJohn.Forte@Sun.COM 			if (verbose) {
1038*7836SJohn.Forte@Sun.COM 				print_cluster_tag(setnumber);
1039*7836SJohn.Forte@Sun.COM 			}
1040*7836SJohn.Forte@Sun.COM 
1041*7836SJohn.Forte@Sun.COM 			(void) printf("\n");
1042*7836SJohn.Forte@Sun.COM 
1043*7836SJohn.Forte@Sun.COM 		} else {
1044*7836SJohn.Forte@Sun.COM 			/*
1045*7836SJohn.Forte@Sun.COM 			 * We didn't find the entry in the hashtable.  Let
1046*7836SJohn.Forte@Sun.COM 			 * the user know that the persistent storage is
1047*7836SJohn.Forte@Sun.COM 			 * inconsistent with the kernel configuration.
1048*7836SJohn.Forte@Sun.COM 			 */
1049*7836SJohn.Forte@Sun.COM 			if (cfg_cluster_tag == NULL)
1050*7836SJohn.Forte@Sun.COM 				warn(NULL, gettext(
1051*7836SJohn.Forte@Sun.COM 					"%s is configured, but not in the "
1052*7836SJohn.Forte@Sun.COM 					"config storage"), svn->svn_path);
1053*7836SJohn.Forte@Sun.COM 		}
1054*7836SJohn.Forte@Sun.COM 	}
1055*7836SJohn.Forte@Sun.COM 
1056*7836SJohn.Forte@Sun.COM 	/* free up the hashtable */
1057*7836SJohn.Forte@Sun.COM 	destroy_hashtable();
1058*7836SJohn.Forte@Sun.COM 
1059*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
1060*7836SJohn.Forte@Sun.COM }
1061*7836SJohn.Forte@Sun.COM 
1062*7836SJohn.Forte@Sun.COM 
1063*7836SJohn.Forte@Sun.COM /* LINT - not static as fwcadm uses it */
1064*7836SJohn.Forte@Sun.COM static int
disable_sv(char * conf_file)1065*7836SJohn.Forte@Sun.COM disable_sv(char *conf_file)
1066*7836SJohn.Forte@Sun.COM {
1067*7836SJohn.Forte@Sun.COM 	sv_name_t *svn, *svn_system;	/* Devices in system */
1068*7836SJohn.Forte@Sun.COM 	sv_list_t svl_system;
1069*7836SJohn.Forte@Sun.COM 	int fd, i, setnumber;
1070*7836SJohn.Forte@Sun.COM 	int rc, ret;
1071*7836SJohn.Forte@Sun.COM 
1072*7836SJohn.Forte@Sun.COM 	svn_system = sv_alloc_svnames();
1073*7836SJohn.Forte@Sun.COM 
1074*7836SJohn.Forte@Sun.COM 	rc = ret = 0;
1075*7836SJohn.Forte@Sun.COM 
1076*7836SJohn.Forte@Sun.COM 	if (conf_file == NULL) {
1077*7836SJohn.Forte@Sun.COM 		if ((fd = open(sv_rpath, O_RDONLY)) < 0) {
1078*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("unable to open %s: %s"),
1079*7836SJohn.Forte@Sun.COM 				sv_rpath, strerror(errno));
1080*7836SJohn.Forte@Sun.COM 			return (1);
1081*7836SJohn.Forte@Sun.COM 		}
1082*7836SJohn.Forte@Sun.COM 
1083*7836SJohn.Forte@Sun.COM 		/* Grab the system list from the driver */
1084*7836SJohn.Forte@Sun.COM 		svl_system.svl_count = sv_max_devices;
1085*7836SJohn.Forte@Sun.COM 		svl_system.svl_names = &svn_system[0];
1086*7836SJohn.Forte@Sun.COM 		svl_system.svl_error = spcs_s_ucreate();
1087*7836SJohn.Forte@Sun.COM 
1088*7836SJohn.Forte@Sun.COM 		if (ioctl(fd, SVIOC_LIST, &svl_system) < 0) {
1089*7836SJohn.Forte@Sun.COM 			error(&(svl_system.svl_error),
1090*7836SJohn.Forte@Sun.COM 					gettext("unable to get list"));
1091*7836SJohn.Forte@Sun.COM 		}
1092*7836SJohn.Forte@Sun.COM 
1093*7836SJohn.Forte@Sun.COM 		spcs_s_ufree(&(svl_system.svl_error));
1094*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1095*7836SJohn.Forte@Sun.COM 	} else {
1096*7836SJohn.Forte@Sun.COM 		svl_system.svl_count = read_config_file(conf_file, svn_system);
1097*7836SJohn.Forte@Sun.COM 	}
1098*7836SJohn.Forte@Sun.COM 
1099*7836SJohn.Forte@Sun.COM 
1100*7836SJohn.Forte@Sun.COM 	for (i = 0; i < svl_system.svl_count; i++) {
1101*7836SJohn.Forte@Sun.COM 		if (*svn_system[i].svn_path == '\0')
1102*7836SJohn.Forte@Sun.COM 			break;
1103*7836SJohn.Forte@Sun.COM 
1104*7836SJohn.Forte@Sun.COM 		svn = &svn_system[i];
1105*7836SJohn.Forte@Sun.COM 
1106*7836SJohn.Forte@Sun.COM 		sv_check_cluster(svn->svn_path);
1107*7836SJohn.Forte@Sun.COM 		sv_cfg_open(CFG_WRLOCK);
1108*7836SJohn.Forte@Sun.COM 		create_cfg_hash();
1109*7836SJohn.Forte@Sun.COM 		rc = 0;
1110*7836SJohn.Forte@Sun.COM 		if ((setnumber = find_in_hash(svn->svn_path)) != -1) {
1111*7836SJohn.Forte@Sun.COM 			if ((rc = disable_dev(svn->svn_path)) != -1) {
1112*7836SJohn.Forte@Sun.COM 				remove_from_cfgfile(svn->svn_path, setnumber);
1113*7836SJohn.Forte@Sun.COM 			} else if (errno == SV_ENODEV) {
1114*7836SJohn.Forte@Sun.COM 				remove_from_cfgfile(svn->svn_path, setnumber);
1115*7836SJohn.Forte@Sun.COM 			}
1116*7836SJohn.Forte@Sun.COM 		} else {
1117*7836SJohn.Forte@Sun.COM 			/* warn the user that we didn't find it in cfg file */
1118*7836SJohn.Forte@Sun.COM 			warn(NULL, gettext(
1119*7836SJohn.Forte@Sun.COM 				"%s was not found in the config storage"),
1120*7836SJohn.Forte@Sun.COM 				svn->svn_path);
1121*7836SJohn.Forte@Sun.COM 			/* try to disable anyway */
1122*7836SJohn.Forte@Sun.COM 			(void) disable_dev(svn->svn_path);
1123*7836SJohn.Forte@Sun.COM 			rc = 1;
1124*7836SJohn.Forte@Sun.COM 		}
1125*7836SJohn.Forte@Sun.COM 
1126*7836SJohn.Forte@Sun.COM 		sv_cfg_close();
1127*7836SJohn.Forte@Sun.COM 		destroy_hashtable();
1128*7836SJohn.Forte@Sun.COM 
1129*7836SJohn.Forte@Sun.COM 		if (rc && !ret)
1130*7836SJohn.Forte@Sun.COM 			ret = rc;
1131*7836SJohn.Forte@Sun.COM 	}
1132*7836SJohn.Forte@Sun.COM 
1133*7836SJohn.Forte@Sun.COM 	return (ret);
1134*7836SJohn.Forte@Sun.COM }
1135*7836SJohn.Forte@Sun.COM 
1136*7836SJohn.Forte@Sun.COM 
1137*7836SJohn.Forte@Sun.COM /* LINT - not static as fwcadm uses it */
1138*7836SJohn.Forte@Sun.COM static int
disable_one_sv(char * path)1139*7836SJohn.Forte@Sun.COM disable_one_sv(char *path)
1140*7836SJohn.Forte@Sun.COM {
1141*7836SJohn.Forte@Sun.COM 	int setnumber;
1142*7836SJohn.Forte@Sun.COM 	int rc;
1143*7836SJohn.Forte@Sun.COM 
1144*7836SJohn.Forte@Sun.COM 	sv_get_maxdevs();
1145*7836SJohn.Forte@Sun.COM 	sv_check_cluster(path);
1146*7836SJohn.Forte@Sun.COM 	sv_cfg_open(CFG_WRLOCK);
1147*7836SJohn.Forte@Sun.COM 
1148*7836SJohn.Forte@Sun.COM 	create_cfg_hash();
1149*7836SJohn.Forte@Sun.COM 	if ((setnumber = find_in_hash(path)) != -1) {
1150*7836SJohn.Forte@Sun.COM 		/* remove from kernel */
1151*7836SJohn.Forte@Sun.COM 		if ((rc = disable_dev(path)) == 0) {
1152*7836SJohn.Forte@Sun.COM 			/* remove the cfgline */
1153*7836SJohn.Forte@Sun.COM 			remove_from_cfgfile(path, setnumber);
1154*7836SJohn.Forte@Sun.COM 		} else if (errno == SV_ENODEV) {
1155*7836SJohn.Forte@Sun.COM 			remove_from_cfgfile(path, setnumber);
1156*7836SJohn.Forte@Sun.COM 		}
1157*7836SJohn.Forte@Sun.COM 	} else {
1158*7836SJohn.Forte@Sun.COM 		/* warn the user that we didn't find it in cfg file */
1159*7836SJohn.Forte@Sun.COM 		warn(NULL,
1160*7836SJohn.Forte@Sun.COM 		    gettext("%s was not found in the config storage"), path);
1161*7836SJohn.Forte@Sun.COM 		/* still attempt to remove */
1162*7836SJohn.Forte@Sun.COM 		(void) disable_dev(path);
1163*7836SJohn.Forte@Sun.COM 		rc = 1;
1164*7836SJohn.Forte@Sun.COM 	}
1165*7836SJohn.Forte@Sun.COM 	destroy_hashtable();
1166*7836SJohn.Forte@Sun.COM 
1167*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
1168*7836SJohn.Forte@Sun.COM 	return (rc);
1169*7836SJohn.Forte@Sun.COM }
1170*7836SJohn.Forte@Sun.COM 
1171*7836SJohn.Forte@Sun.COM 
1172*7836SJohn.Forte@Sun.COM static void
compare_tag(char * path)1173*7836SJohn.Forte@Sun.COM compare_tag(char *path)
1174*7836SJohn.Forte@Sun.COM {
1175*7836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF], vol[CFG_MAX_BUF], cnode[CFG_MAX_BUF];
1176*7836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
1177*7836SJohn.Forte@Sun.COM 	int found, setnumber, i;
1178*7836SJohn.Forte@Sun.COM 	char *tag;
1179*7836SJohn.Forte@Sun.COM 
1180*7836SJohn.Forte@Sun.COM 	sv_check_cluster(path);
1181*7836SJohn.Forte@Sun.COM 	cfg_resource(cfg, (char *)NULL);	/* reset */
1182*7836SJohn.Forte@Sun.COM 	cfg_rewind(cfg, CFG_SEC_CONF);
1183*7836SJohn.Forte@Sun.COM 
1184*7836SJohn.Forte@Sun.COM #ifdef DEBUG
1185*7836SJohn.Forte@Sun.COM 	if (cfg_cluster_tag != NULL && implicit_tag != NULL) {
1186*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("compare_tag: -C %s AND implicit_tag %s!"),
1187*7836SJohn.Forte@Sun.COM 		    cfg_cluster_tag, implicit_tag);
1188*7836SJohn.Forte@Sun.COM 	}
1189*7836SJohn.Forte@Sun.COM #endif
1190*7836SJohn.Forte@Sun.COM 
1191*7836SJohn.Forte@Sun.COM 	if (cfg_cluster_tag != NULL)
1192*7836SJohn.Forte@Sun.COM 		tag = cfg_cluster_tag;
1193*7836SJohn.Forte@Sun.COM 	else if (implicit_tag != NULL)
1194*7836SJohn.Forte@Sun.COM 		tag = implicit_tag;
1195*7836SJohn.Forte@Sun.COM 	else
1196*7836SJohn.Forte@Sun.COM 		tag = "-";
1197*7836SJohn.Forte@Sun.COM 
1198*7836SJohn.Forte@Sun.COM 	found = 0;
1199*7836SJohn.Forte@Sun.COM 	for (i = 0; i < sv_max_devices; i++) {
1200*7836SJohn.Forte@Sun.COM 		setnumber = i + 1;
1201*7836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "sv.set%d", setnumber);
1202*7836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
1203*7836SJohn.Forte@Sun.COM 			break;
1204*7836SJohn.Forte@Sun.COM 		}
1205*7836SJohn.Forte@Sun.COM 
1206*7836SJohn.Forte@Sun.COM 		if (sscanf(buf, "%s - %s", vol, cnode) != 2) {
1207*7836SJohn.Forte@Sun.COM 			continue;
1208*7836SJohn.Forte@Sun.COM 		}
1209*7836SJohn.Forte@Sun.COM 
1210*7836SJohn.Forte@Sun.COM 		if (strcmp(path, vol) == 0) {
1211*7836SJohn.Forte@Sun.COM 			found = 1;
1212*7836SJohn.Forte@Sun.COM 			break;
1213*7836SJohn.Forte@Sun.COM 		}
1214*7836SJohn.Forte@Sun.COM 	}
1215*7836SJohn.Forte@Sun.COM 
1216*7836SJohn.Forte@Sun.COM 	if (!found) {
1217*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("unable to find %s in the configuration"),
1218*7836SJohn.Forte@Sun.COM 		    path);
1219*7836SJohn.Forte@Sun.COM 		return;
1220*7836SJohn.Forte@Sun.COM 	}
1221*7836SJohn.Forte@Sun.COM 
1222*7836SJohn.Forte@Sun.COM 	/* have name match, compare cnode to new tag */
1223*7836SJohn.Forte@Sun.COM 
1224*7836SJohn.Forte@Sun.COM 	if (strcmp(tag, cnode) == 0) {
1225*7836SJohn.Forte@Sun.COM 		/* cluster tags match */
1226*7836SJohn.Forte@Sun.COM 		return;
1227*7836SJohn.Forte@Sun.COM 	}
1228*7836SJohn.Forte@Sun.COM 
1229*7836SJohn.Forte@Sun.COM 	/* need to change the cluster tag */
1230*7836SJohn.Forte@Sun.COM 
1231*7836SJohn.Forte@Sun.COM 	(void) snprintf(key, sizeof (key), "sv.set%d.cnode", setnumber);
1232*7836SJohn.Forte@Sun.COM 	if (cfg_put_cstring(cfg, key, tag, strlen(tag)) < 0) {
1233*7836SJohn.Forte@Sun.COM 		warn(NULL,
1234*7836SJohn.Forte@Sun.COM 		    gettext("unable to change cluster tag for %s"), path);
1235*7836SJohn.Forte@Sun.COM 		return;
1236*7836SJohn.Forte@Sun.COM 	}
1237*7836SJohn.Forte@Sun.COM 
1238*7836SJohn.Forte@Sun.COM 	cfg_changed = 1;
1239*7836SJohn.Forte@Sun.COM 
1240*7836SJohn.Forte@Sun.COM 	/* change "-" tags to "" for display purposes */
1241*7836SJohn.Forte@Sun.COM 
1242*7836SJohn.Forte@Sun.COM 	if (strcmp(tag, "-") == 0)
1243*7836SJohn.Forte@Sun.COM 		tag = "";
1244*7836SJohn.Forte@Sun.COM 
1245*7836SJohn.Forte@Sun.COM 	if (strcmp(cnode, "-") == 0)
1246*7836SJohn.Forte@Sun.COM 		(void) strcpy(cnode, "");
1247*7836SJohn.Forte@Sun.COM 
1248*7836SJohn.Forte@Sun.COM 	(void) printf(
1249*7836SJohn.Forte@Sun.COM 	    gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\"\n"),
1250*7836SJohn.Forte@Sun.COM 	    program, path, cnode, tag);
1251*7836SJohn.Forte@Sun.COM 
1252*7836SJohn.Forte@Sun.COM 	spcs_log("sv", NULL,
1253*7836SJohn.Forte@Sun.COM 	    gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\""),
1254*7836SJohn.Forte@Sun.COM 	    program, path, cnode, tag);
1255*7836SJohn.Forte@Sun.COM }
1256*7836SJohn.Forte@Sun.COM 
1257*7836SJohn.Forte@Sun.COM 
1258*7836SJohn.Forte@Sun.COM /* LINT - not static as fwcadm uses it */
1259*7836SJohn.Forte@Sun.COM static void
compare_sv(char * conf_file)1260*7836SJohn.Forte@Sun.COM compare_sv(char *conf_file)
1261*7836SJohn.Forte@Sun.COM {
1262*7836SJohn.Forte@Sun.COM 	sv_name_t *svn_config;		/* Devices in config file */
1263*7836SJohn.Forte@Sun.COM 	sv_name_t *svn_system;		/* Devices in system */
1264*7836SJohn.Forte@Sun.COM 	sv_name_t *enable;		/* Devices that need enabled */
1265*7836SJohn.Forte@Sun.COM 	sv_list_t svl_system;
1266*7836SJohn.Forte@Sun.COM 	int config_cnt;
1267*7836SJohn.Forte@Sun.COM 	int sys_cnt = 0;
1268*7836SJohn.Forte@Sun.COM 	int setnumber, i, j;
1269*7836SJohn.Forte@Sun.COM 	int index = 0;	/* Index in enable[] */
1270*7836SJohn.Forte@Sun.COM 	int found;
1271*7836SJohn.Forte@Sun.COM 	int fd0;
1272*7836SJohn.Forte@Sun.COM 
1273*7836SJohn.Forte@Sun.COM 	svn_config = sv_alloc_svnames();
1274*7836SJohn.Forte@Sun.COM 	svn_system = sv_alloc_svnames();
1275*7836SJohn.Forte@Sun.COM 	enable = sv_alloc_svnames();
1276*7836SJohn.Forte@Sun.COM 
1277*7836SJohn.Forte@Sun.COM 	bzero(svn_system, sizeof (svn_system));
1278*7836SJohn.Forte@Sun.COM 	bzero(&svl_system, sizeof (svl_system));
1279*7836SJohn.Forte@Sun.COM 	bzero(enable, sizeof (enable));
1280*7836SJohn.Forte@Sun.COM 
1281*7836SJohn.Forte@Sun.COM 	/*
1282*7836SJohn.Forte@Sun.COM 	 * Read the configuration file
1283*7836SJohn.Forte@Sun.COM 	 * The return value is the number of entries
1284*7836SJohn.Forte@Sun.COM 	 */
1285*7836SJohn.Forte@Sun.COM 	config_cnt = read_config_file(conf_file, svn_config);
1286*7836SJohn.Forte@Sun.COM 
1287*7836SJohn.Forte@Sun.COM 	if ((fd0 = open(sv_rpath, O_RDONLY)) < 0)
1288*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to open %s: %s"),
1289*7836SJohn.Forte@Sun.COM 			sv_rpath, strerror(errno));
1290*7836SJohn.Forte@Sun.COM 
1291*7836SJohn.Forte@Sun.COM 	/* Grab the system list from the driver */
1292*7836SJohn.Forte@Sun.COM 	svl_system.svl_count = sv_max_devices;
1293*7836SJohn.Forte@Sun.COM 	svl_system.svl_names = &svn_system[0];
1294*7836SJohn.Forte@Sun.COM 	svl_system.svl_error = spcs_s_ucreate();
1295*7836SJohn.Forte@Sun.COM 
1296*7836SJohn.Forte@Sun.COM 	if (ioctl(fd0, SVIOC_LIST, &svl_system) < 0) {
1297*7836SJohn.Forte@Sun.COM 		error(&svl_system.svl_error, gettext("unable to get list"));
1298*7836SJohn.Forte@Sun.COM 	}
1299*7836SJohn.Forte@Sun.COM 
1300*7836SJohn.Forte@Sun.COM 	spcs_s_ufree(&svl_system.svl_error);
1301*7836SJohn.Forte@Sun.COM 	(void) close(fd0);
1302*7836SJohn.Forte@Sun.COM 
1303*7836SJohn.Forte@Sun.COM 	/*
1304*7836SJohn.Forte@Sun.COM 	 * Count the number of devices in the system.
1305*7836SJohn.Forte@Sun.COM 	 * The last entry in the array has '\0' for a path name.
1306*7836SJohn.Forte@Sun.COM 	 */
1307*7836SJohn.Forte@Sun.COM 	for (j = 0; j < sv_max_devices; j++) {
1308*7836SJohn.Forte@Sun.COM 		if (svn_system[j].svn_path[0] != '\0') {
1309*7836SJohn.Forte@Sun.COM 			sys_cnt++;
1310*7836SJohn.Forte@Sun.COM 		} else {
1311*7836SJohn.Forte@Sun.COM 			break;
1312*7836SJohn.Forte@Sun.COM 		}
1313*7836SJohn.Forte@Sun.COM 	}
1314*7836SJohn.Forte@Sun.COM 	/*
1315*7836SJohn.Forte@Sun.COM 	 * Compare the configuration array with the system array.
1316*7836SJohn.Forte@Sun.COM 	 * Mark any differences and disable conflicting devices.
1317*7836SJohn.Forte@Sun.COM 	 */
1318*7836SJohn.Forte@Sun.COM 	for (i = 0; i < config_cnt; i++) {
1319*7836SJohn.Forte@Sun.COM 		found = 0;
1320*7836SJohn.Forte@Sun.COM 		for (j = 0; j < sys_cnt; j++) {
1321*7836SJohn.Forte@Sun.COM 			if (svn_system[j].svn_path[0] == '\0' ||
1322*7836SJohn.Forte@Sun.COM 			    svn_system[j].svn_mode == 0)
1323*7836SJohn.Forte@Sun.COM 				continue;
1324*7836SJohn.Forte@Sun.COM 
1325*7836SJohn.Forte@Sun.COM 			/*  Check to see if path matches */
1326*7836SJohn.Forte@Sun.COM 			if (strcmp(svn_system[j].svn_path,
1327*7836SJohn.Forte@Sun.COM 			    svn_config[i].svn_path) == 0) {
1328*7836SJohn.Forte@Sun.COM 				/*  Found a match  */
1329*7836SJohn.Forte@Sun.COM 				svn_system[j].svn_path[0] = '\0';
1330*7836SJohn.Forte@Sun.COM 				found++;
1331*7836SJohn.Forte@Sun.COM 				break;
1332*7836SJohn.Forte@Sun.COM 			}
1333*7836SJohn.Forte@Sun.COM 		}
1334*7836SJohn.Forte@Sun.COM 
1335*7836SJohn.Forte@Sun.COM 		if (!found) {
1336*7836SJohn.Forte@Sun.COM 			/* Minor number not in system  = > enable device */
1337*7836SJohn.Forte@Sun.COM 			enable[index].svn_mode = svn_config[i].svn_mode;
1338*7836SJohn.Forte@Sun.COM 			(void) strcpy(enable[index].svn_path,
1339*7836SJohn.Forte@Sun.COM 			    svn_config[i].svn_path);
1340*7836SJohn.Forte@Sun.COM 			index++;
1341*7836SJohn.Forte@Sun.COM 		}
1342*7836SJohn.Forte@Sun.COM 	}
1343*7836SJohn.Forte@Sun.COM 
1344*7836SJohn.Forte@Sun.COM 	/* Disable any devices that weren't in the config file */
1345*7836SJohn.Forte@Sun.COM 	for (j = 0; j < sys_cnt; j++) {
1346*7836SJohn.Forte@Sun.COM 		sv_check_cluster(NULL);
1347*7836SJohn.Forte@Sun.COM 		sv_cfg_open(CFG_WRLOCK);
1348*7836SJohn.Forte@Sun.COM 		create_cfg_hash();
1349*7836SJohn.Forte@Sun.COM 		if (svn_system[j].svn_path[0] != '\0' &&
1350*7836SJohn.Forte@Sun.COM 		    svn_system[j].svn_mode != 0) {
1351*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("%s: disabling sv: %s\n"),
1352*7836SJohn.Forte@Sun.COM 			    program, svn_system[j].svn_path);
1353*7836SJohn.Forte@Sun.COM 			if (disable_dev(svn_system[j].svn_path) == 0) {
1354*7836SJohn.Forte@Sun.COM 				setnumber =
1355*7836SJohn.Forte@Sun.COM 					find_in_hash(svn_system[j].svn_path);
1356*7836SJohn.Forte@Sun.COM 				if (setnumber != -1) {
1357*7836SJohn.Forte@Sun.COM 					/* the volume was found in cfg store */
1358*7836SJohn.Forte@Sun.COM 					remove_from_cfgfile(
1359*7836SJohn.Forte@Sun.COM 					svn_system[j].svn_path, setnumber);
1360*7836SJohn.Forte@Sun.COM 				}
1361*7836SJohn.Forte@Sun.COM 			}
1362*7836SJohn.Forte@Sun.COM 		}
1363*7836SJohn.Forte@Sun.COM 		sv_cfg_close();
1364*7836SJohn.Forte@Sun.COM 		destroy_hashtable();
1365*7836SJohn.Forte@Sun.COM 	}
1366*7836SJohn.Forte@Sun.COM 
1367*7836SJohn.Forte@Sun.COM 	while (index) {
1368*7836SJohn.Forte@Sun.COM 		/*
1369*7836SJohn.Forte@Sun.COM 		 * Config file doesn't match system => enable the devices
1370*7836SJohn.Forte@Sun.COM 		 * in enable[]
1371*7836SJohn.Forte@Sun.COM 		 */
1372*7836SJohn.Forte@Sun.COM 		index--;
1373*7836SJohn.Forte@Sun.COM 		(void) printf(gettext("%s: enabling new sv: %s\n"),
1374*7836SJohn.Forte@Sun.COM 		    program, enable[index].svn_path);
1375*7836SJohn.Forte@Sun.COM 		(void) enable_dev(&enable[index]);
1376*7836SJohn.Forte@Sun.COM 	}
1377*7836SJohn.Forte@Sun.COM 
1378*7836SJohn.Forte@Sun.COM 	/*
1379*7836SJohn.Forte@Sun.COM 	 * Search for entries where the cluster tag has changed.
1380*7836SJohn.Forte@Sun.COM 	 */
1381*7836SJohn.Forte@Sun.COM 	sv_check_cluster(NULL);
1382*7836SJohn.Forte@Sun.COM 	sv_cfg_open(CFG_WRLOCK);
1383*7836SJohn.Forte@Sun.COM 
1384*7836SJohn.Forte@Sun.COM 	for (i = 0; i < sv_max_devices; i++) {
1385*7836SJohn.Forte@Sun.COM 		if (svn_config[i].svn_path[0] == '\0')
1386*7836SJohn.Forte@Sun.COM 			break;
1387*7836SJohn.Forte@Sun.COM 
1388*7836SJohn.Forte@Sun.COM 		compare_tag(svn_config[i].svn_path);
1389*7836SJohn.Forte@Sun.COM 	}
1390*7836SJohn.Forte@Sun.COM 
1391*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
1392*7836SJohn.Forte@Sun.COM }
1393*7836SJohn.Forte@Sun.COM 
1394*7836SJohn.Forte@Sun.COM 
1395*7836SJohn.Forte@Sun.COM /*
1396*7836SJohn.Forte@Sun.COM  * We assume that the volume is already enabled and we can only
1397*7836SJohn.Forte@Sun.COM  * be changing the cluster tag.  Anything else is an error.
1398*7836SJohn.Forte@Sun.COM  */
1399*7836SJohn.Forte@Sun.COM /* LINT - not static as fwcadm uses it */
1400*7836SJohn.Forte@Sun.COM static void
compare_one_sv(char * path)1401*7836SJohn.Forte@Sun.COM compare_one_sv(char *path)
1402*7836SJohn.Forte@Sun.COM {
1403*7836SJohn.Forte@Sun.COM 	sv_get_maxdevs();
1404*7836SJohn.Forte@Sun.COM 	sv_check_cluster(NULL);
1405*7836SJohn.Forte@Sun.COM 	sv_cfg_open(CFG_WRLOCK);
1406*7836SJohn.Forte@Sun.COM 
1407*7836SJohn.Forte@Sun.COM 	compare_tag(path);
1408*7836SJohn.Forte@Sun.COM 
1409*7836SJohn.Forte@Sun.COM 	sv_cfg_close();
1410*7836SJohn.Forte@Sun.COM }
1411*7836SJohn.Forte@Sun.COM 
1412*7836SJohn.Forte@Sun.COM /*
1413*7836SJohn.Forte@Sun.COM  * Read all sets from the libdscfg configuration file, and store everything in
1414*7836SJohn.Forte@Sun.COM  * the hashfile.
1415*7836SJohn.Forte@Sun.COM  *
1416*7836SJohn.Forte@Sun.COM  * We assume that the config file has been opened & rewound for us.  We store
1417*7836SJohn.Forte@Sun.COM  * the volume name as the key, and the setnumber where we found it as the data.
1418*7836SJohn.Forte@Sun.COM  *
1419*7836SJohn.Forte@Sun.COM  * The caller can pass in a pointer to the maximum number of volumes, or
1420*7836SJohn.Forte@Sun.COM  * a pointer to NULL, specifying we want 'all' the volumes.  The table is
1421*7836SJohn.Forte@Sun.COM  * searched using find_in_hash.
1422*7836SJohn.Forte@Sun.COM  */
1423*7836SJohn.Forte@Sun.COM static void
create_cfg_hash()1424*7836SJohn.Forte@Sun.COM create_cfg_hash()
1425*7836SJohn.Forte@Sun.COM {
1426*7836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
1427*7836SJohn.Forte@Sun.COM 	char vol[CFG_MAX_BUF], cnode[CFG_MAX_BUF];
1428*7836SJohn.Forte@Sun.COM 	int setnumber;
1429*7836SJohn.Forte@Sun.COM 	ENTRY item;
1430*7836SJohn.Forte@Sun.COM 
1431*7836SJohn.Forte@Sun.COM 	if (hcreate((size_t)sv_max_devices) == 0)
1432*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to create hash table"));
1433*7836SJohn.Forte@Sun.COM 
1434*7836SJohn.Forte@Sun.COM 	for (setnumber = 1; /* CSTYLED */; setnumber++) {
1435*7836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "sv.set%d", setnumber);
1436*7836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
1437*7836SJohn.Forte@Sun.COM 			break;
1438*7836SJohn.Forte@Sun.COM 
1439*7836SJohn.Forte@Sun.COM 		if (sscanf(buf, "%s - %s", vol, cnode) != 2) {
1440*7836SJohn.Forte@Sun.COM 			continue;
1441*7836SJohn.Forte@Sun.COM 		}
1442*7836SJohn.Forte@Sun.COM 
1443*7836SJohn.Forte@Sun.COM 		item.key = strdup(vol);
1444*7836SJohn.Forte@Sun.COM 		item.data = (void *)setnumber;
1445*7836SJohn.Forte@Sun.COM 		if (hsearch(item, ENTER) == NULL) {
1446*7836SJohn.Forte@Sun.COM 			error(NULL,
1447*7836SJohn.Forte@Sun.COM 			    gettext("unable to add entry to hash table"));
1448*7836SJohn.Forte@Sun.COM 		}
1449*7836SJohn.Forte@Sun.COM 	}
1450*7836SJohn.Forte@Sun.COM }
1451*7836SJohn.Forte@Sun.COM 
1452*7836SJohn.Forte@Sun.COM /*
1453*7836SJohn.Forte@Sun.COM  * Function to search the hash for a specific volume.  If it is found,
1454*7836SJohn.Forte@Sun.COM  * we return the set number.  If it isn't found, we return -1
1455*7836SJohn.Forte@Sun.COM  */
1456*7836SJohn.Forte@Sun.COM static int
find_in_hash(char * path)1457*7836SJohn.Forte@Sun.COM find_in_hash(char *path)
1458*7836SJohn.Forte@Sun.COM {
1459*7836SJohn.Forte@Sun.COM 	ENTRY *found_entry, item;
1460*7836SJohn.Forte@Sun.COM 	int retval = -1;
1461*7836SJohn.Forte@Sun.COM 
1462*7836SJohn.Forte@Sun.COM 	item.key = path;
1463*7836SJohn.Forte@Sun.COM 
1464*7836SJohn.Forte@Sun.COM 	if ((found_entry = hsearch(item, FIND)) != NULL) {
1465*7836SJohn.Forte@Sun.COM 		retval = (int)found_entry->data;
1466*7836SJohn.Forte@Sun.COM 	}
1467*7836SJohn.Forte@Sun.COM 
1468*7836SJohn.Forte@Sun.COM 	return (retval);
1469*7836SJohn.Forte@Sun.COM }
1470*7836SJohn.Forte@Sun.COM 
1471*7836SJohn.Forte@Sun.COM /*
1472*7836SJohn.Forte@Sun.COM  * Just a wrapper to destory the hashtable.  At some point in the future we
1473*7836SJohn.Forte@Sun.COM  * might want to do something more....  For instance, verify that the cfg
1474*7836SJohn.Forte@Sun.COM  * database and the kernel configuration match (?)  Just an idea.
1475*7836SJohn.Forte@Sun.COM  */
1476*7836SJohn.Forte@Sun.COM static void
destroy_hashtable()1477*7836SJohn.Forte@Sun.COM destroy_hashtable()
1478*7836SJohn.Forte@Sun.COM {
1479*7836SJohn.Forte@Sun.COM 	hdestroy();
1480*7836SJohn.Forte@Sun.COM }
1481*7836SJohn.Forte@Sun.COM 
1482*7836SJohn.Forte@Sun.COM /*
1483*7836SJohn.Forte@Sun.COM  * This function will remove a particular set from the config file.
1484*7836SJohn.Forte@Sun.COM  *
1485*7836SJohn.Forte@Sun.COM  * We make a whole host of assumptions:
1486*7836SJohn.Forte@Sun.COM  *   o the hashfile is up to date;
1487*7836SJohn.Forte@Sun.COM  *   o The config file has been opened with a WRLOCK for us.
1488*7836SJohn.Forte@Sun.COM  */
1489*7836SJohn.Forte@Sun.COM static void
remove_from_cfgfile(char * path,int setnumber)1490*7836SJohn.Forte@Sun.COM remove_from_cfgfile(char *path, int setnumber)
1491*7836SJohn.Forte@Sun.COM {
1492*7836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
1493*7836SJohn.Forte@Sun.COM 	int sev;
1494*7836SJohn.Forte@Sun.COM 	char *lcltag;
1495*7836SJohn.Forte@Sun.COM 
1496*7836SJohn.Forte@Sun.COM 	/* attempt to remove the volume from config storage */
1497*7836SJohn.Forte@Sun.COM 	(void) snprintf(key, sizeof (key), "sv.set%d", setnumber);
1498*7836SJohn.Forte@Sun.COM 	if (cfg_put_cstring(cfg, key, NULL, 0) < 0) {
1499*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("unable to remove %s from "
1500*7836SJohn.Forte@Sun.COM 		    "config storage: %s"), path, cfg_error(&sev));
1501*7836SJohn.Forte@Sun.COM 	} else {
1502*7836SJohn.Forte@Sun.COM 		if (implicit_tag && *implicit_tag) {
1503*7836SJohn.Forte@Sun.COM 			lcltag = implicit_tag;
1504*7836SJohn.Forte@Sun.COM 		} else if (cfg_cluster_tag && *cfg_cluster_tag) {
1505*7836SJohn.Forte@Sun.COM 			lcltag = cfg_cluster_tag;
1506*7836SJohn.Forte@Sun.COM 		} else {
1507*7836SJohn.Forte@Sun.COM 			lcltag = "-";
1508*7836SJohn.Forte@Sun.COM 		}
1509*7836SJohn.Forte@Sun.COM 		if (cfg_rem_user(cfg, path, lcltag, "sv") != CFG_USER_LAST) {
1510*7836SJohn.Forte@Sun.COM 			warn(NULL, gettext("unable to remove %s from dsvol"),
1511*7836SJohn.Forte@Sun.COM 			    path);
1512*7836SJohn.Forte@Sun.COM 		}
1513*7836SJohn.Forte@Sun.COM 		cfg_changed = 1;
1514*7836SJohn.Forte@Sun.COM 	}
1515*7836SJohn.Forte@Sun.COM }
1516