xref: /titanic_53/usr/src/cmd/avs/dsw/iiadm.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <sys/types.h>
27*fcf3ce44SJohn Forte #include <sys/time.h>
28*fcf3ce44SJohn Forte #include <errno.h>
29*fcf3ce44SJohn Forte #include <signal.h>
30*fcf3ce44SJohn Forte #include <stdio.h>
31*fcf3ce44SJohn Forte #include <string.h>
32*fcf3ce44SJohn Forte #include <fcntl.h>
33*fcf3ce44SJohn Forte #include <stdlib.h>
34*fcf3ce44SJohn Forte #include <unistd.h>
35*fcf3ce44SJohn Forte #include <values.h>
36*fcf3ce44SJohn Forte #include <locale.h>
37*fcf3ce44SJohn Forte #include <langinfo.h>
38*fcf3ce44SJohn Forte #include <sys/mman.h>
39*fcf3ce44SJohn Forte #include <sys/stat.h>
40*fcf3ce44SJohn Forte #include <sys/wait.h>
41*fcf3ce44SJohn Forte #include <strings.h>
42*fcf3ce44SJohn Forte #include <stdarg.h>
43*fcf3ce44SJohn Forte #include <ctype.h>
44*fcf3ce44SJohn Forte #include <math.h>
45*fcf3ce44SJohn Forte #include <sys/param.h>
46*fcf3ce44SJohn Forte #include <sys/mnttab.h>
47*fcf3ce44SJohn Forte #include <nsctl.h>
48*fcf3ce44SJohn Forte #include <netdb.h>
49*fcf3ce44SJohn Forte #include <search.h>
50*fcf3ce44SJohn Forte 
51*fcf3ce44SJohn Forte #include <sys/nsctl/cfg.h>
52*fcf3ce44SJohn Forte #include <sys/nsctl/nsc_hash.h>
53*fcf3ce44SJohn Forte 
54*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s.h>
55*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_u.h>
56*fcf3ce44SJohn Forte #include <sys/unistat/spcs_errors.h>
57*fcf3ce44SJohn Forte #include <sys/nsctl/dsw.h>
58*fcf3ce44SJohn Forte #include <sys/nsctl/dsw_dev.h>		/* for bit map header format */
59*fcf3ce44SJohn Forte 
60*fcf3ce44SJohn Forte #include <sys/nskernd.h>
61*fcf3ce44SJohn Forte 
62*fcf3ce44SJohn Forte typedef struct mstcount_s {
63*fcf3ce44SJohn Forte 	int count;
64*fcf3ce44SJohn Forte } mstcount_t;
65*fcf3ce44SJohn Forte typedef struct shdvol_s {
66*fcf3ce44SJohn Forte 	char master[ DSW_NAMELEN ];
67*fcf3ce44SJohn Forte } shdvol_t;
68*fcf3ce44SJohn Forte typedef struct grptag_s {
69*fcf3ce44SJohn Forte 	char ctag[ DSW_NAMELEN ];
70*fcf3ce44SJohn Forte } grptag_t;
71*fcf3ce44SJohn Forte hash_node_t **volhash = NULL;
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte #define	DSW_TEXT_DOMAIN	"II"
74*fcf3ce44SJohn Forte 
75*fcf3ce44SJohn Forte #include <dlfcn.h>
76*fcf3ce44SJohn Forte #define	RDC_LIB "/usr/lib/librdc.so.1"
77*fcf3ce44SJohn Forte static int (*self_check)(char *);
78*fcf3ce44SJohn Forte 
79*fcf3ce44SJohn Forte /*
80*fcf3ce44SJohn Forte  * Support for the special cluster tag "local" to be used with -C in a
81*fcf3ce44SJohn Forte  * cluster for local volumes.
82*fcf3ce44SJohn Forte  */
83*fcf3ce44SJohn Forte #define	II_LOCAL_TAG	"local"
84*fcf3ce44SJohn Forte 
85*fcf3ce44SJohn Forte #define	II_NOT_CLUSTER	1
86*fcf3ce44SJohn Forte #define	II_CLUSTER	2
87*fcf3ce44SJohn Forte #define	II_CLUSTER_LCL	3
88*fcf3ce44SJohn Forte 
89*fcf3ce44SJohn Forte static char *cfg_cluster_tag = NULL;
90*fcf3ce44SJohn Forte static CFGFILE *cfg = NULL;
91*fcf3ce44SJohn Forte 
92*fcf3ce44SJohn Forte void sigterm(int sig);
93*fcf3ce44SJohn Forte 
94*fcf3ce44SJohn Forte #define	SD_BIT_CLR(bmap, bit)		(bmap &= ~(1 << bit))
95*fcf3ce44SJohn Forte #define	SD_BIT_ISSET(bmap, bit)		((bmap & (1 << bit)) != 0)
96*fcf3ce44SJohn Forte 
97*fcf3ce44SJohn Forte #define	MAX_LINE_SIZE 256	/* maximum characters per line in config file */
98*fcf3ce44SJohn Forte #define	MAX_GROUPS 1024		/* maximum number of groups to support */
99*fcf3ce44SJohn Forte #define	MAX_CLUSTERS 1024	/* maximum number of resource groups */
100*fcf3ce44SJohn Forte 
101*fcf3ce44SJohn Forte unsigned long	bm_size;		/* size in bytes of bitmap */
102*fcf3ce44SJohn Forte unsigned long	bm_actual;		/* original number of bits in bitmap */
103*fcf3ce44SJohn Forte int	debug = 0;
104*fcf3ce44SJohn Forte 
105*fcf3ce44SJohn Forte int	dsw_fd;
106*fcf3ce44SJohn Forte 
107*fcf3ce44SJohn Forte #define	LD_II		0x00000001
108*fcf3ce44SJohn Forte #define	LD_DSVOLS	0x00000002
109*fcf3ce44SJohn Forte #define	LD_SVOLS	0x00000004
110*fcf3ce44SJohn Forte #define	LD_SHADOWS	0x00000008
111*fcf3ce44SJohn Forte 
112*fcf3ce44SJohn Forte static int reload_vols = 0;
113*fcf3ce44SJohn Forte static int config_locked = 0;
114*fcf3ce44SJohn Forte static int last_lock;
115*fcf3ce44SJohn Forte 
116*fcf3ce44SJohn Forte /*
117*fcf3ce44SJohn Forte  * names for do_copy() flags.
118*fcf3ce44SJohn Forte  */
119*fcf3ce44SJohn Forte 
120*fcf3ce44SJohn Forte enum	copy_update {Copy = 0, Update};
121*fcf3ce44SJohn Forte enum	copy_direction {ToShadow = 0, ToMaster};
122*fcf3ce44SJohn Forte enum	copy_wait {WaitForStart = 0, WaitForEnd};
123*fcf3ce44SJohn Forte 
124*fcf3ce44SJohn Forte char	*cmdnam;
125*fcf3ce44SJohn Forte 
126*fcf3ce44SJohn Forte unsigned char	*allocate_bitmap(char *);
127*fcf3ce44SJohn Forte void		usage(char *);
128*fcf3ce44SJohn Forte void		enable(char *, char *, char *, char *);
129*fcf3ce44SJohn Forte int		disable(char *);
130*fcf3ce44SJohn Forte void		bitmap_op(char *, int, int, int, int);
131*fcf3ce44SJohn Forte void		print_status(dsw_config_t *, int);
132*fcf3ce44SJohn Forte int		abort_copy(char *);
133*fcf3ce44SJohn Forte int		reset(char *);
134*fcf3ce44SJohn Forte int		overflow(char *);
135*fcf3ce44SJohn Forte void		iiversion(void);
136*fcf3ce44SJohn Forte int		wait_for_copy(char *);
137*fcf3ce44SJohn Forte int		export(char *);
138*fcf3ce44SJohn Forte void		list_volumes(void);
139*fcf3ce44SJohn Forte void		dsw_error(char *, spcs_s_info_t *);
140*fcf3ce44SJohn Forte void		InitEnv();
141*fcf3ce44SJohn Forte static void	check_dg_is_local(char *dgname);
142*fcf3ce44SJohn Forte static int	check_resource_group(char *volume);
143*fcf3ce44SJohn Forte static int	check_diskgroup(char *path, char *result);
144*fcf3ce44SJohn Forte static int	check_cluster();
145*fcf3ce44SJohn Forte static void	unload_ii_vols();
146*fcf3ce44SJohn Forte static void	load_ii_vols(CFGFILE *);
147*fcf3ce44SJohn Forte static int	perform_autosv();
148*fcf3ce44SJohn Forte static int	is_exported(char *);
149*fcf3ce44SJohn Forte static void	conform_name(char **);
150*fcf3ce44SJohn Forte static void	do_attach(dsw_config_t *);
151*fcf3ce44SJohn Forte static int	ii_lock(CFGFILE *, int);
152*fcf3ce44SJohn Forte static void	verify_groupname(char *grp, int testDash);
153*fcf3ce44SJohn Forte 
154*fcf3ce44SJohn Forte void	dsw_list_clusters(char *);
155*fcf3ce44SJohn Forte void	dsw_enable(int, char **);
156*fcf3ce44SJohn Forte void	dsw_disable(int, char **);
157*fcf3ce44SJohn Forte void	dsw_copy_to_shadow(int, char **);
158*fcf3ce44SJohn Forte void	dsw_update_shadow(int, char **);
159*fcf3ce44SJohn Forte void	dsw_copy_to_master(int, char **);
160*fcf3ce44SJohn Forte void	dsw_update_master(int, char **);
161*fcf3ce44SJohn Forte void	dsw_abort_copy(int, char **);
162*fcf3ce44SJohn Forte void	dsw_display_status(int, char **);
163*fcf3ce44SJohn Forte void	dsw_display_bitmap(int, char **);
164*fcf3ce44SJohn Forte void	dsw_reset(int, char **);
165*fcf3ce44SJohn Forte void	dsw_overflow(int, char **);
166*fcf3ce44SJohn Forte void	dsw_version(int, char **);
167*fcf3ce44SJohn Forte void	dsw_wait(int, char **);
168*fcf3ce44SJohn Forte void	dsw_list_volumes(int, char **);
169*fcf3ce44SJohn Forte void	dsw_list_group_volumes();
170*fcf3ce44SJohn Forte void	dsw_export(int, char **);
171*fcf3ce44SJohn Forte void	dsw_import(int, char **);
172*fcf3ce44SJohn Forte void	dsw_join(int, char **);
173*fcf3ce44SJohn Forte void	dsw_attach(int, char **);
174*fcf3ce44SJohn Forte void	dsw_detach(int, char **);
175*fcf3ce44SJohn Forte void	dsw_params(int, char **);
176*fcf3ce44SJohn Forte void	dsw_olist(int, char **);
177*fcf3ce44SJohn Forte void	dsw_ostat(int, char **);
178*fcf3ce44SJohn Forte void	dsw_move_2_group(int, char **);
179*fcf3ce44SJohn Forte void	dsw_list_groups();
180*fcf3ce44SJohn Forte void	check_iishadow(char *);
181*fcf3ce44SJohn Forte 
182*fcf3ce44SJohn Forte extern char *optarg;
183*fcf3ce44SJohn Forte extern int optind, opterr, optopt;
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte int	Aflg;
186*fcf3ce44SJohn Forte int	Cflg;
187*fcf3ce44SJohn Forte int	CLflg;
188*fcf3ce44SJohn Forte int	Dflg;
189*fcf3ce44SJohn Forte int	Eflg;
190*fcf3ce44SJohn Forte int	Iflg;
191*fcf3ce44SJohn Forte int	Jflg;
192*fcf3ce44SJohn Forte int	Lflg;
193*fcf3ce44SJohn Forte int	Oflg;
194*fcf3ce44SJohn Forte int	Pflg;
195*fcf3ce44SJohn Forte int	Qflg;
196*fcf3ce44SJohn Forte int	Rflg;
197*fcf3ce44SJohn Forte int	aflg;
198*fcf3ce44SJohn Forte int	bflg;
199*fcf3ce44SJohn Forte int	cflg;
200*fcf3ce44SJohn Forte int	dflg;
201*fcf3ce44SJohn Forte int	eflg;
202*fcf3ce44SJohn Forte int	fflg;
203*fcf3ce44SJohn Forte int	gflg;
204*fcf3ce44SJohn Forte int	gLflg;
205*fcf3ce44SJohn Forte int	hflg;
206*fcf3ce44SJohn Forte int	iflg;
207*fcf3ce44SJohn Forte int	lflg;
208*fcf3ce44SJohn Forte int	mflg;
209*fcf3ce44SJohn Forte int	nflg;
210*fcf3ce44SJohn Forte int	pflg;
211*fcf3ce44SJohn Forte int	uflg;
212*fcf3ce44SJohn Forte int	vflg;
213*fcf3ce44SJohn Forte int	wflg;
214*fcf3ce44SJohn Forte 
215*fcf3ce44SJohn Forte int	errflg;
216*fcf3ce44SJohn Forte #ifdef DEBUG
217*fcf3ce44SJohn Forte const char single_opts[] =
218*fcf3ce44SJohn Forte 	"a:b:c:d:e:f:g:hilmnpu:vw:A:C:D:E:I:J:LO:PQ:R:";
219*fcf3ce44SJohn Forte #else
220*fcf3ce44SJohn Forte /* no b or f flags */
221*fcf3ce44SJohn Forte const char single_opts[] = "a:c:d:e:g:hilmnpu:vw:A:C:D:E:I:J:LO:PQ:R:";
222*fcf3ce44SJohn Forte #endif
223*fcf3ce44SJohn Forte const char group_opts[] = "ac:de:ilmnpu:wA:C:DELPR";
224*fcf3ce44SJohn Forte const char *opt_list = single_opts;
225*fcf3ce44SJohn Forte 
226*fcf3ce44SJohn Forte char	buf[CFG_MAX_BUF];
227*fcf3ce44SJohn Forte char	key[CFG_MAX_KEY];
228*fcf3ce44SJohn Forte char	last_overflow[DSW_NAMELEN];
229*fcf3ce44SJohn Forte int	setnumber;
230*fcf3ce44SJohn Forte char	*group_name;
231*fcf3ce44SJohn Forte char	**group_volumes;
232*fcf3ce44SJohn Forte enum copy_direction direction;
233*fcf3ce44SJohn Forte char	*param_delay, *param_unit;
234*fcf3ce44SJohn Forte char	*overflow_file;
235*fcf3ce44SJohn Forte 
236*fcf3ce44SJohn Forte #ifdef lint
237*fcf3ce44SJohn Forte int
238*fcf3ce44SJohn Forte iiadm_lintmain(int argc, char *argv[])
239*fcf3ce44SJohn Forte #else
240*fcf3ce44SJohn Forte int
241*fcf3ce44SJohn Forte main(int argc, char *argv[])
242*fcf3ce44SJohn Forte #endif
243*fcf3ce44SJohn Forte {
244*fcf3ce44SJohn Forte 	int c;
245*fcf3ce44SJohn Forte 	int actions = 0;
246*fcf3ce44SJohn Forte 	int ac;
247*fcf3ce44SJohn Forte 	char *av[1024];
248*fcf3ce44SJohn Forte 
249*fcf3ce44SJohn Forte 	InitEnv();
250*fcf3ce44SJohn Forte 
251*fcf3ce44SJohn Forte 	memset(av, 0, sizeof (av));
252*fcf3ce44SJohn Forte 	cmdnam = argv[0];
253*fcf3ce44SJohn Forte 	while ((c = getopt(argc, argv, opt_list)) != EOF)
254*fcf3ce44SJohn Forte 		switch (c) {
255*fcf3ce44SJohn Forte 		case 'c':
256*fcf3ce44SJohn Forte 			cflg++;
257*fcf3ce44SJohn Forte 			actions++;
258*fcf3ce44SJohn Forte 			if (strcmp(optarg, "m") == 0) {
259*fcf3ce44SJohn Forte 				av[0] = "copy_to_master";
260*fcf3ce44SJohn Forte 				direction = ToMaster;
261*fcf3ce44SJohn Forte 			} else if (strcmp(optarg, "s") == 0) {
262*fcf3ce44SJohn Forte 				av[0] = "copy_to_shadow";
263*fcf3ce44SJohn Forte 				direction = ToShadow;
264*fcf3ce44SJohn Forte 			} else {
265*fcf3ce44SJohn Forte 				errflg ++;
266*fcf3ce44SJohn Forte 				usage(gettext(
267*fcf3ce44SJohn Forte 					"must specify m or s with -c"));
268*fcf3ce44SJohn Forte 			}
269*fcf3ce44SJohn Forte 			ac = 2;
270*fcf3ce44SJohn Forte 			break;
271*fcf3ce44SJohn Forte 		case 'd':
272*fcf3ce44SJohn Forte 			dflg++;
273*fcf3ce44SJohn Forte 			actions++;
274*fcf3ce44SJohn Forte 			av[0] = "disable";
275*fcf3ce44SJohn Forte 			av[1] = optarg;
276*fcf3ce44SJohn Forte 			ac = 2;
277*fcf3ce44SJohn Forte 			break;
278*fcf3ce44SJohn Forte 		case 'e':
279*fcf3ce44SJohn Forte 			eflg++;
280*fcf3ce44SJohn Forte 			actions++;
281*fcf3ce44SJohn Forte 			av[0] = "enable";
282*fcf3ce44SJohn Forte 			if (strcmp(optarg, "ind") == 0)
283*fcf3ce44SJohn Forte 				av[4] = "independent";
284*fcf3ce44SJohn Forte 			else if (strcmp(optarg, "dep") == 0)
285*fcf3ce44SJohn Forte 				av[4] = "dependent";
286*fcf3ce44SJohn Forte 			else {
287*fcf3ce44SJohn Forte 				errflg ++;
288*fcf3ce44SJohn Forte 				usage(gettext(
289*fcf3ce44SJohn Forte 					"must specify ind or dep with -e"));
290*fcf3ce44SJohn Forte 			}
291*fcf3ce44SJohn Forte 			ac = 1;
292*fcf3ce44SJohn Forte 			break;
293*fcf3ce44SJohn Forte 		case 'g':
294*fcf3ce44SJohn Forte 			gflg++;
295*fcf3ce44SJohn Forte 			opt_list = group_opts;
296*fcf3ce44SJohn Forte 			group_name = optarg;
297*fcf3ce44SJohn Forte 			if (group_name && *group_name == '-') {
298*fcf3ce44SJohn Forte 				gLflg = (strcmp("-L", group_name) == 0);
299*fcf3ce44SJohn Forte 				if (gLflg)
300*fcf3ce44SJohn Forte 					actions++;
301*fcf3ce44SJohn Forte 			}
302*fcf3ce44SJohn Forte 			verify_groupname(group_name, !gLflg);
303*fcf3ce44SJohn Forte 			break;
304*fcf3ce44SJohn Forte 		case 'h':
305*fcf3ce44SJohn Forte 			hflg++;
306*fcf3ce44SJohn Forte 			actions++;
307*fcf3ce44SJohn Forte 			break;
308*fcf3ce44SJohn Forte 		case 'u':
309*fcf3ce44SJohn Forte 			uflg++;
310*fcf3ce44SJohn Forte 			actions++;
311*fcf3ce44SJohn Forte 			if (strcmp(optarg, "m") == 0) {
312*fcf3ce44SJohn Forte 				av[0] = "update_master";
313*fcf3ce44SJohn Forte 				direction = ToMaster;
314*fcf3ce44SJohn Forte 			} else if (strcmp(optarg, "s") == 0) {
315*fcf3ce44SJohn Forte 				av[0] = "update_shadow";
316*fcf3ce44SJohn Forte 				direction = ToShadow;
317*fcf3ce44SJohn Forte 			} else {
318*fcf3ce44SJohn Forte 				errflg ++;
319*fcf3ce44SJohn Forte 				usage(gettext(
320*fcf3ce44SJohn Forte 					"must specify m or s with -u"));
321*fcf3ce44SJohn Forte 			}
322*fcf3ce44SJohn Forte 			ac = 2;
323*fcf3ce44SJohn Forte 			break;
324*fcf3ce44SJohn Forte 		case 'i':
325*fcf3ce44SJohn Forte 			iflg++;
326*fcf3ce44SJohn Forte 			actions++;
327*fcf3ce44SJohn Forte 			av[0] = "display_status";
328*fcf3ce44SJohn Forte 			break;
329*fcf3ce44SJohn Forte 		case 'l':
330*fcf3ce44SJohn Forte 			lflg++;
331*fcf3ce44SJohn Forte 			actions++;
332*fcf3ce44SJohn Forte 			av[0] = "list_config";
333*fcf3ce44SJohn Forte 			ac = 1;
334*fcf3ce44SJohn Forte 			break;
335*fcf3ce44SJohn Forte 		case 'm':
336*fcf3ce44SJohn Forte 			mflg++;
337*fcf3ce44SJohn Forte 			actions++;
338*fcf3ce44SJohn Forte 			av[0] = "move_to_group";
339*fcf3ce44SJohn Forte 			ac = 1;
340*fcf3ce44SJohn Forte 			break;
341*fcf3ce44SJohn Forte 		case 'n':
342*fcf3ce44SJohn Forte 			nflg++;
343*fcf3ce44SJohn Forte 			break;
344*fcf3ce44SJohn Forte 		case 'p':
345*fcf3ce44SJohn Forte 			pflg++;
346*fcf3ce44SJohn Forte 			break;
347*fcf3ce44SJohn Forte 		case 'b':
348*fcf3ce44SJohn Forte 			bflg++;
349*fcf3ce44SJohn Forte 			actions++;
350*fcf3ce44SJohn Forte 			av[0] = "display_bitmap";
351*fcf3ce44SJohn Forte 			av[1] = optarg;
352*fcf3ce44SJohn Forte 			ac = 2;
353*fcf3ce44SJohn Forte 			break;
354*fcf3ce44SJohn Forte 		case 'a':
355*fcf3ce44SJohn Forte 			aflg++;
356*fcf3ce44SJohn Forte 			actions++;
357*fcf3ce44SJohn Forte 			av[0] = "abort_copy";
358*fcf3ce44SJohn Forte 			av[1] = optarg;
359*fcf3ce44SJohn Forte 			ac = 2;
360*fcf3ce44SJohn Forte 			break;
361*fcf3ce44SJohn Forte 		case 'v':
362*fcf3ce44SJohn Forte 			vflg++;
363*fcf3ce44SJohn Forte 			actions++;
364*fcf3ce44SJohn Forte 			av[1] = "version";
365*fcf3ce44SJohn Forte 			ac = 1;
366*fcf3ce44SJohn Forte 			break;
367*fcf3ce44SJohn Forte 		case 'w':
368*fcf3ce44SJohn Forte 			wflg++;
369*fcf3ce44SJohn Forte 			actions++;
370*fcf3ce44SJohn Forte 			av[0] = "wait";
371*fcf3ce44SJohn Forte 			av[1] = optarg;
372*fcf3ce44SJohn Forte 			ac = 2;
373*fcf3ce44SJohn Forte 			break;
374*fcf3ce44SJohn Forte 		case 'A':
375*fcf3ce44SJohn Forte 			Aflg++;
376*fcf3ce44SJohn Forte 			actions++;
377*fcf3ce44SJohn Forte 			av[0] = "attach";
378*fcf3ce44SJohn Forte 			av[1] = optarg;
379*fcf3ce44SJohn Forte 			ac = 2;
380*fcf3ce44SJohn Forte 			break;
381*fcf3ce44SJohn Forte 		case 'C':
382*fcf3ce44SJohn Forte 			Cflg++;
383*fcf3ce44SJohn Forte 			cfg_cluster_tag = optarg;
384*fcf3ce44SJohn Forte 			if (cfg_cluster_tag && *cfg_cluster_tag == '-') {
385*fcf3ce44SJohn Forte 				CLflg = (strcmp("-L", cfg_cluster_tag) == 0);
386*fcf3ce44SJohn Forte 				if (CLflg)
387*fcf3ce44SJohn Forte 					actions++;
388*fcf3ce44SJohn Forte 			}
389*fcf3ce44SJohn Forte 			break;
390*fcf3ce44SJohn Forte 		case 'D':
391*fcf3ce44SJohn Forte 			Dflg++;
392*fcf3ce44SJohn Forte 			actions++;
393*fcf3ce44SJohn Forte 			av[0] = "detach";
394*fcf3ce44SJohn Forte 			av[1] = optarg;
395*fcf3ce44SJohn Forte 			ac = 2;
396*fcf3ce44SJohn Forte 			break;
397*fcf3ce44SJohn Forte 		case 'O':
398*fcf3ce44SJohn Forte 			Oflg++;
399*fcf3ce44SJohn Forte 			actions++;
400*fcf3ce44SJohn Forte 			av[0] = "overflow";
401*fcf3ce44SJohn Forte 			av[1] = optarg;
402*fcf3ce44SJohn Forte 			ac = 2;
403*fcf3ce44SJohn Forte 			break;
404*fcf3ce44SJohn Forte 		case 'R':
405*fcf3ce44SJohn Forte 			Rflg++;
406*fcf3ce44SJohn Forte 			actions++;
407*fcf3ce44SJohn Forte 			av[0] = "reset";
408*fcf3ce44SJohn Forte 			av[1] = optarg;
409*fcf3ce44SJohn Forte 			ac = 2;
410*fcf3ce44SJohn Forte 			break;
411*fcf3ce44SJohn Forte 		case 'E':
412*fcf3ce44SJohn Forte 			Eflg++;
413*fcf3ce44SJohn Forte 			actions++;
414*fcf3ce44SJohn Forte 			av[0] = "export";
415*fcf3ce44SJohn Forte 			av[1] = optarg;
416*fcf3ce44SJohn Forte 			ac = 2;
417*fcf3ce44SJohn Forte 			break;
418*fcf3ce44SJohn Forte 		case 'I':
419*fcf3ce44SJohn Forte 			Iflg++;
420*fcf3ce44SJohn Forte 			actions++;
421*fcf3ce44SJohn Forte 			av[0] = "import";
422*fcf3ce44SJohn Forte 			av[1] = optarg;
423*fcf3ce44SJohn Forte 			ac = 2;
424*fcf3ce44SJohn Forte 			break;
425*fcf3ce44SJohn Forte 		case 'J':
426*fcf3ce44SJohn Forte 			Jflg++;
427*fcf3ce44SJohn Forte 			actions++;
428*fcf3ce44SJohn Forte 			av[0] = "join";
429*fcf3ce44SJohn Forte 			av[1] = optarg;
430*fcf3ce44SJohn Forte 			ac = 2;
431*fcf3ce44SJohn Forte 			break;
432*fcf3ce44SJohn Forte 		case 'P':
433*fcf3ce44SJohn Forte 			Pflg++;
434*fcf3ce44SJohn Forte 			actions++;
435*fcf3ce44SJohn Forte 			av[0] = "parameter";
436*fcf3ce44SJohn Forte 			ac = 1;
437*fcf3ce44SJohn Forte 			break;
438*fcf3ce44SJohn Forte 		case 'L':
439*fcf3ce44SJohn Forte 			Lflg++;
440*fcf3ce44SJohn Forte 			actions++;
441*fcf3ce44SJohn Forte 			/* If -g group -L, force error */
442*fcf3ce44SJohn Forte 			if (group_name) actions++;
443*fcf3ce44SJohn Forte 			av[0] = "LIST";
444*fcf3ce44SJohn Forte 			ac = 1;
445*fcf3ce44SJohn Forte 			break;
446*fcf3ce44SJohn Forte 		case 'Q':
447*fcf3ce44SJohn Forte 			Qflg++;
448*fcf3ce44SJohn Forte 			actions++;
449*fcf3ce44SJohn Forte 			av[0] = "query";
450*fcf3ce44SJohn Forte 			av[1] = optarg;
451*fcf3ce44SJohn Forte 			ac = 2;
452*fcf3ce44SJohn Forte 			break;
453*fcf3ce44SJohn Forte 		case '?':
454*fcf3ce44SJohn Forte 			errflg++;
455*fcf3ce44SJohn Forte 			break;
456*fcf3ce44SJohn Forte 		}
457*fcf3ce44SJohn Forte 	if (hflg) {
458*fcf3ce44SJohn Forte 		usage(NULL);
459*fcf3ce44SJohn Forte 		exit(0);
460*fcf3ce44SJohn Forte 		}
461*fcf3ce44SJohn Forte 
462*fcf3ce44SJohn Forte 	if (errflg)
463*fcf3ce44SJohn Forte 		usage(gettext("unrecognized argument"));
464*fcf3ce44SJohn Forte 	switch (actions) {
465*fcf3ce44SJohn Forte 		case 0:
466*fcf3ce44SJohn Forte 			if (argc > 1)
467*fcf3ce44SJohn Forte 				usage(gettext("must specify an action flag"));
468*fcf3ce44SJohn Forte 
469*fcf3ce44SJohn Forte 			/* default behavior is to list configuration */
470*fcf3ce44SJohn Forte 			lflg++; av[0] = "list_config"; ac = 1;
471*fcf3ce44SJohn Forte 			break;
472*fcf3ce44SJohn Forte 		case 1:
473*fcf3ce44SJohn Forte 			break;
474*fcf3ce44SJohn Forte 		default:
475*fcf3ce44SJohn Forte 			usage(gettext("too many action flags"));
476*fcf3ce44SJohn Forte 			break;
477*fcf3ce44SJohn Forte 	}
478*fcf3ce44SJohn Forte 
479*fcf3ce44SJohn Forte 	if (gflg && (Iflg || Jflg || Oflg || Qflg))
480*fcf3ce44SJohn Forte 		usage(gettext("can't use a group with this option"));
481*fcf3ce44SJohn Forte 	if (!gflg && (mflg))
482*fcf3ce44SJohn Forte 		usage(gettext("must use a group with this option"));
483*fcf3ce44SJohn Forte 
484*fcf3ce44SJohn Forte 	/*
485*fcf3ce44SJohn Forte 	 * Open configuration file.
486*fcf3ce44SJohn Forte 	 */
487*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
488*fcf3ce44SJohn Forte 		perror("unable to access configuration");
489*fcf3ce44SJohn Forte 		exit(2);
490*fcf3ce44SJohn Forte 	}
491*fcf3ce44SJohn Forte 
492*fcf3ce44SJohn Forte 	/*
493*fcf3ce44SJohn Forte 	 * Set write locking (CFG_WRLOCK) for:
494*fcf3ce44SJohn Forte 	 *	iiadm -e (enable)
495*fcf3ce44SJohn Forte 	 * 	iiadm -d (disable)
496*fcf3ce44SJohn Forte 	 *	iiadm -A (attach overflow)
497*fcf3ce44SJohn Forte 	 *	iiadm -D (detach overflow)
498*fcf3ce44SJohn Forte 	 *	iiadm -g grp -m volume (move volume into group)
499*fcf3ce44SJohn Forte 	 *	iiadm -E (export shadow [needs to update dsvol section])
500*fcf3ce44SJohn Forte 	 *	iiadm -I (import shadow [ditto])
501*fcf3ce44SJohn Forte 	 *	iiadm -J (join shadow [ditto])
502*fcf3ce44SJohn Forte 	 * read locking (CFG_RDLOCK) for all other commands
503*fcf3ce44SJohn Forte 	 */
504*fcf3ce44SJohn Forte 	last_lock = (eflg || dflg || mflg || Aflg || Dflg || Eflg || Iflg ||
505*fcf3ce44SJohn Forte 	    Jflg)? CFG_WRLOCK : CFG_RDLOCK;
506*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, last_lock)) {
507*fcf3ce44SJohn Forte 		perror("unable to lock configuration");
508*fcf3ce44SJohn Forte 		exit(2);
509*fcf3ce44SJohn Forte 	}
510*fcf3ce44SJohn Forte 	config_locked = 1;
511*fcf3ce44SJohn Forte 
512*fcf3ce44SJohn Forte 	/*
513*fcf3ce44SJohn Forte 	 * If we are in a cluster, set or derive a valid disk group
514*fcf3ce44SJohn Forte 	 */
515*fcf3ce44SJohn Forte 	switch (check_cluster()) {
516*fcf3ce44SJohn Forte 	case II_CLUSTER:
517*fcf3ce44SJohn Forte 		/*
518*fcf3ce44SJohn Forte 		 * If in a Sun Cluster, can't Import an II shadow
519*fcf3ce44SJohn Forte 		 * Must be done as -C local
520*fcf3ce44SJohn Forte 		 */
521*fcf3ce44SJohn Forte 		if (Iflg)
522*fcf3ce44SJohn Forte 			dsw_error(gettext(
523*fcf3ce44SJohn Forte 				"-I (import) only allowed as -C local"), NULL);
524*fcf3ce44SJohn Forte 		/*FALLTHRU*/
525*fcf3ce44SJohn Forte 	case II_CLUSTER_LCL:
526*fcf3ce44SJohn Forte 		/*
527*fcf3ce44SJohn Forte 		 * If a cluster tag was specified or derived, set it
528*fcf3ce44SJohn Forte 		 */
529*fcf3ce44SJohn Forte 		if (CLflg) {
530*fcf3ce44SJohn Forte 			dsw_list_clusters(argv[optind]);
531*fcf3ce44SJohn Forte 			cfg_close(cfg);
532*fcf3ce44SJohn Forte 			exit(0);
533*fcf3ce44SJohn Forte 		} else {
534*fcf3ce44SJohn Forte 			cfg_resource(cfg, cfg_cluster_tag);
535*fcf3ce44SJohn Forte 		}
536*fcf3ce44SJohn Forte 		break;
537*fcf3ce44SJohn Forte 	case II_NOT_CLUSTER:
538*fcf3ce44SJohn Forte 		if (cfg_cluster_tag != NULL)
539*fcf3ce44SJohn Forte 			dsw_error(gettext(
540*fcf3ce44SJohn Forte 			    "-C is valid only in a Sun Cluster"), NULL);
541*fcf3ce44SJohn Forte 		break;
542*fcf3ce44SJohn Forte 	default:
543*fcf3ce44SJohn Forte 		dsw_error(gettext(
544*fcf3ce44SJohn Forte 		    "Unexpected return from check_cluster()"), NULL);
545*fcf3ce44SJohn Forte 	}
546*fcf3ce44SJohn Forte 
547*fcf3ce44SJohn Forte 	/* preload the ii config */
548*fcf3ce44SJohn Forte 	load_ii_vols(cfg);
549*fcf3ce44SJohn Forte 	reload_vols |= LD_II;
550*fcf3ce44SJohn Forte 
551*fcf3ce44SJohn Forte 	if (eflg) {
552*fcf3ce44SJohn Forte 		if (argc - optind != 3)
553*fcf3ce44SJohn Forte 			usage(gettext("must specify 3 volumes with -e"));
554*fcf3ce44SJohn Forte 		av[1] = argv[optind++];
555*fcf3ce44SJohn Forte 		av[2] = argv[optind++];
556*fcf3ce44SJohn Forte 		av[3] = argv[optind++];
557*fcf3ce44SJohn Forte 		ac = 5;
558*fcf3ce44SJohn Forte 		dsw_enable(ac, av);
559*fcf3ce44SJohn Forte 	} else if (dflg) {
560*fcf3ce44SJohn Forte 		dsw_disable(ac, av);
561*fcf3ce44SJohn Forte 	} else if (uflg) {
562*fcf3ce44SJohn Forte 		if (argv[optind] == NULL && group_name == NULL)
563*fcf3ce44SJohn Forte 			usage(gettext("must specify volume with -u"));
564*fcf3ce44SJohn Forte 		for (c = 1; argv[optind] != NULL; optind++)
565*fcf3ce44SJohn Forte 			av[c++] = argv[optind];
566*fcf3ce44SJohn Forte 		av[c] = NULL;
567*fcf3ce44SJohn Forte 
568*fcf3ce44SJohn Forte 		if (direction == ToMaster)
569*fcf3ce44SJohn Forte 			dsw_update_master(ac, av);
570*fcf3ce44SJohn Forte 		else
571*fcf3ce44SJohn Forte 			dsw_update_shadow(ac, av);
572*fcf3ce44SJohn Forte 	} else if (iflg) {
573*fcf3ce44SJohn Forte 		if (argv[optind]) {
574*fcf3ce44SJohn Forte 			av[1] = argv[optind];
575*fcf3ce44SJohn Forte 			ac = 2;
576*fcf3ce44SJohn Forte 		} else
577*fcf3ce44SJohn Forte 			ac = 1;
578*fcf3ce44SJohn Forte 		dsw_display_status(ac, av);
579*fcf3ce44SJohn Forte 	} else if (bflg) {
580*fcf3ce44SJohn Forte 		dsw_display_bitmap(ac, av);
581*fcf3ce44SJohn Forte 	} else if (cflg) {
582*fcf3ce44SJohn Forte 		if (argv[optind] == NULL && group_name == NULL)
583*fcf3ce44SJohn Forte 			usage(gettext("must specify volume with -c"));
584*fcf3ce44SJohn Forte 		for (c = 1; argv[optind] != NULL; optind++)
585*fcf3ce44SJohn Forte 			av[c++] = argv[optind];
586*fcf3ce44SJohn Forte 		av[c] = NULL;
587*fcf3ce44SJohn Forte 
588*fcf3ce44SJohn Forte 		if (direction == ToMaster)
589*fcf3ce44SJohn Forte 			dsw_copy_to_master(ac, av);
590*fcf3ce44SJohn Forte 		else
591*fcf3ce44SJohn Forte 			dsw_copy_to_shadow(ac, av);
592*fcf3ce44SJohn Forte 	} else if (aflg) {
593*fcf3ce44SJohn Forte 		dsw_abort_copy(ac, av);
594*fcf3ce44SJohn Forte 	} else if (Eflg) {
595*fcf3ce44SJohn Forte 		dsw_export(ac, av);
596*fcf3ce44SJohn Forte 	} else if (Iflg) {
597*fcf3ce44SJohn Forte 		if (argc - optind != 1)
598*fcf3ce44SJohn Forte 			usage(gettext("must specify 2 volumes with -I"));
599*fcf3ce44SJohn Forte 		av[2] = argv[optind++];
600*fcf3ce44SJohn Forte 		ac = 3;
601*fcf3ce44SJohn Forte 		dsw_import(ac, av);
602*fcf3ce44SJohn Forte 	} else if (Aflg) {
603*fcf3ce44SJohn Forte 		if (group_name) {
604*fcf3ce44SJohn Forte 			if (argc - optind != 0)
605*fcf3ce44SJohn Forte 				usage(gettext("must specify overflow volume " \
606*fcf3ce44SJohn Forte 				"when using groups with -A"));
607*fcf3ce44SJohn Forte 			ac = 2;
608*fcf3ce44SJohn Forte 		} else {
609*fcf3ce44SJohn Forte 			if (argc - optind != 1)
610*fcf3ce44SJohn Forte 				usage(gettext("specify 2 volumes with -A"));
611*fcf3ce44SJohn Forte 			ac = 3;
612*fcf3ce44SJohn Forte 			av[2] = argv[optind++];
613*fcf3ce44SJohn Forte 		}
614*fcf3ce44SJohn Forte 		dsw_attach(ac, av);
615*fcf3ce44SJohn Forte 	} else if (Dflg) {
616*fcf3ce44SJohn Forte 		dsw_detach(ac, av);
617*fcf3ce44SJohn Forte 	} else if (Jflg) {
618*fcf3ce44SJohn Forte 		if (argc - optind != 1)
619*fcf3ce44SJohn Forte 			usage(gettext("must specify 2 volumes with -J"));
620*fcf3ce44SJohn Forte 		av[2] = argv[optind++];
621*fcf3ce44SJohn Forte 		ac = 3;
622*fcf3ce44SJohn Forte 		dsw_join(ac, av);
623*fcf3ce44SJohn Forte 	} else if (Pflg) {
624*fcf3ce44SJohn Forte 		if (argc - optind == ((group_name) ? 0 : 1)) {
625*fcf3ce44SJohn Forte 			av[1] = argv[optind++];
626*fcf3ce44SJohn Forte 			ac = (group_name) ? 0 : 2;
627*fcf3ce44SJohn Forte 		} else if (argc - optind == ((group_name) ? 2 : 3)) {
628*fcf3ce44SJohn Forte 			av[1] = argv[optind++];
629*fcf3ce44SJohn Forte 			av[2] = argv[optind++];
630*fcf3ce44SJohn Forte 			av[3] = argv[optind++];
631*fcf3ce44SJohn Forte 			ac = (group_name) ? 2 : 4;
632*fcf3ce44SJohn Forte 		} else
633*fcf3ce44SJohn Forte 			usage(gettext(
634*fcf3ce44SJohn Forte 				"must specify delay, unit and shadow with -P"));
635*fcf3ce44SJohn Forte 		dsw_params(ac, av);
636*fcf3ce44SJohn Forte 	} else if (Oflg) {
637*fcf3ce44SJohn Forte 		dsw_overflow(ac, av);
638*fcf3ce44SJohn Forte 	} else if (Rflg) {
639*fcf3ce44SJohn Forte 		dsw_reset(ac, av);
640*fcf3ce44SJohn Forte 	} else if (vflg) {
641*fcf3ce44SJohn Forte 		dsw_version(ac, av);
642*fcf3ce44SJohn Forte 	} else if (wflg) {
643*fcf3ce44SJohn Forte 		dsw_wait(ac, av);
644*fcf3ce44SJohn Forte 	} else if (lflg) {
645*fcf3ce44SJohn Forte 		if ((gflg) && (!group_name))
646*fcf3ce44SJohn Forte 			dsw_list_group_volumes();
647*fcf3ce44SJohn Forte 		else
648*fcf3ce44SJohn Forte 			dsw_list_volumes(ac, av);
649*fcf3ce44SJohn Forte 	} else if (Lflg) {
650*fcf3ce44SJohn Forte 		dsw_olist(ac, av);
651*fcf3ce44SJohn Forte 	} else if (gLflg) {
652*fcf3ce44SJohn Forte 		dsw_list_groups();
653*fcf3ce44SJohn Forte 	} else if (Qflg) {
654*fcf3ce44SJohn Forte 		dsw_ostat(ac, av);
655*fcf3ce44SJohn Forte 	} else if (mflg) {
656*fcf3ce44SJohn Forte 		if (argc - optind < 1)
657*fcf3ce44SJohn Forte 			usage(gettext("must specify one or more volumes"));
658*fcf3ce44SJohn Forte 		for (c = 1; argv[optind] != NULL; optind++)
659*fcf3ce44SJohn Forte 			av[c++] = argv[optind];
660*fcf3ce44SJohn Forte 		av[c] = NULL;
661*fcf3ce44SJohn Forte 		dsw_move_2_group(ac, av);
662*fcf3ce44SJohn Forte 	}
663*fcf3ce44SJohn Forte 	if (cfg)
664*fcf3ce44SJohn Forte 		cfg_close(cfg);
665*fcf3ce44SJohn Forte 
666*fcf3ce44SJohn Forte 	exit(0);
667*fcf3ce44SJohn Forte 	return (0);
668*fcf3ce44SJohn Forte }
669*fcf3ce44SJohn Forte 
670*fcf3ce44SJohn Forte static int
671*fcf3ce44SJohn Forte ii_lock(CFGFILE *cfg, int locktype)
672*fcf3ce44SJohn Forte {
673*fcf3ce44SJohn Forte 	last_lock = locktype;
674*fcf3ce44SJohn Forte 	return (cfg_lock(cfg, locktype));
675*fcf3ce44SJohn Forte }
676*fcf3ce44SJohn Forte 
677*fcf3ce44SJohn Forte static int
678*fcf3ce44SJohn Forte do_ioctl(int fd, int cmd, void *arg)
679*fcf3ce44SJohn Forte {
680*fcf3ce44SJohn Forte 	int unlocked = 0;
681*fcf3ce44SJohn Forte 	int rc;
682*fcf3ce44SJohn Forte 	int save_errno;
683*fcf3ce44SJohn Forte 
684*fcf3ce44SJohn Forte 	if (config_locked) {
685*fcf3ce44SJohn Forte 		switch (cmd) {
686*fcf3ce44SJohn Forte 		case DSWIOC_ENABLE:
687*fcf3ce44SJohn Forte 		case DSWIOC_RESUME:
688*fcf3ce44SJohn Forte 		case DSWIOC_SUSPEND:
689*fcf3ce44SJohn Forte 		case DSWIOC_COPY:
690*fcf3ce44SJohn Forte 		case DSWIOC_BITMAP:
691*fcf3ce44SJohn Forte 		case DSWIOC_DISABLE:
692*fcf3ce44SJohn Forte 		case DSWIOC_SHUTDOWN:
693*fcf3ce44SJohn Forte 		case DSWIOC_ABORT:
694*fcf3ce44SJohn Forte 		case DSWIOC_RESET:
695*fcf3ce44SJohn Forte 		case DSWIOC_OFFLINE:
696*fcf3ce44SJohn Forte 		case DSWIOC_WAIT:
697*fcf3ce44SJohn Forte 		case DSWIOC_ACOPY:
698*fcf3ce44SJohn Forte 		case DSWIOC_EXPORT:
699*fcf3ce44SJohn Forte 		case DSWIOC_IMPORT:
700*fcf3ce44SJohn Forte 		case DSWIOC_JOIN:
701*fcf3ce44SJohn Forte 		case DSWIOC_COPYP:
702*fcf3ce44SJohn Forte 		case DSWIOC_OATTACH:
703*fcf3ce44SJohn Forte 		case DSWIOC_ODETACH:
704*fcf3ce44SJohn Forte 		case DSWIOC_SBITSSET:
705*fcf3ce44SJohn Forte 		case DSWIOC_CBITSSET:
706*fcf3ce44SJohn Forte 		case DSWIOC_SEGMENT:
707*fcf3ce44SJohn Forte 		case DSWIOC_MOVEGRP:
708*fcf3ce44SJohn Forte 		case DSWIOC_CHANGETAG:
709*fcf3ce44SJohn Forte 			cfg_unlock(cfg);
710*fcf3ce44SJohn Forte 			unlocked = 1;
711*fcf3ce44SJohn Forte 			break;
712*fcf3ce44SJohn Forte 
713*fcf3ce44SJohn Forte 		case DSWIOC_STAT:
714*fcf3ce44SJohn Forte 		case DSWIOC_VERSION:
715*fcf3ce44SJohn Forte 		case DSWIOC_LIST:
716*fcf3ce44SJohn Forte 		case DSWIOC_OCREAT:
717*fcf3ce44SJohn Forte 		case DSWIOC_OLIST:
718*fcf3ce44SJohn Forte 		case DSWIOC_OSTAT:
719*fcf3ce44SJohn Forte 		case DSWIOC_OSTAT2:
720*fcf3ce44SJohn Forte 		case DSWIOC_LISTLEN:
721*fcf3ce44SJohn Forte 		case DSWIOC_OLISTLEN:
722*fcf3ce44SJohn Forte 		case DSWIOC_CLIST:
723*fcf3ce44SJohn Forte 		case DSWIOC_GLIST:
724*fcf3ce44SJohn Forte 			break;
725*fcf3ce44SJohn Forte 
726*fcf3ce44SJohn Forte 		default:
727*fcf3ce44SJohn Forte 			fprintf(stderr,
728*fcf3ce44SJohn Forte 			    "cfg locking needs to be set for %08x\n", cmd);
729*fcf3ce44SJohn Forte 			exit(1);
730*fcf3ce44SJohn Forte 			break;
731*fcf3ce44SJohn Forte 		}
732*fcf3ce44SJohn Forte 	}
733*fcf3ce44SJohn Forte 	if (unlocked) {
734*fcf3ce44SJohn Forte 		/* unload vol hashes */
735*fcf3ce44SJohn Forte 		if (reload_vols & LD_II)
736*fcf3ce44SJohn Forte 			unload_ii_vols();
737*fcf3ce44SJohn Forte 		if (reload_vols & LD_SHADOWS)
738*fcf3ce44SJohn Forte 			cfg_unload_shadows();
739*fcf3ce44SJohn Forte 		if (reload_vols & LD_DSVOLS)
740*fcf3ce44SJohn Forte 			cfg_unload_dsvols();
741*fcf3ce44SJohn Forte 		if (reload_vols & LD_SVOLS)
742*fcf3ce44SJohn Forte 			cfg_unload_svols();
743*fcf3ce44SJohn Forte 	}
744*fcf3ce44SJohn Forte 	rc = ioctl(fd, cmd, arg);
745*fcf3ce44SJohn Forte 	save_errno = errno;
746*fcf3ce44SJohn Forte 	if (config_locked && unlocked) {
747*fcf3ce44SJohn Forte 		cfg_lock(cfg, last_lock);
748*fcf3ce44SJohn Forte 	}
749*fcf3ce44SJohn Forte 	if (unlocked) {
750*fcf3ce44SJohn Forte 		/* reload vol hashes */
751*fcf3ce44SJohn Forte 		if (reload_vols & LD_SVOLS)
752*fcf3ce44SJohn Forte 			cfg_load_svols(cfg);
753*fcf3ce44SJohn Forte 		if (reload_vols & LD_DSVOLS)
754*fcf3ce44SJohn Forte 			cfg_load_dsvols(cfg);
755*fcf3ce44SJohn Forte 		if (reload_vols & LD_SHADOWS)
756*fcf3ce44SJohn Forte 			cfg_load_shadows(cfg);
757*fcf3ce44SJohn Forte 		if (reload_vols & LD_II)
758*fcf3ce44SJohn Forte 			load_ii_vols(cfg);
759*fcf3ce44SJohn Forte 	}
760*fcf3ce44SJohn Forte 
761*fcf3ce44SJohn Forte 	errno = save_errno;
762*fcf3ce44SJohn Forte 	return (rc);
763*fcf3ce44SJohn Forte }
764*fcf3ce44SJohn Forte 
765*fcf3ce44SJohn Forte static int
766*fcf3ce44SJohn Forte get_dsw_config(int setno, dsw_config_t *parms)
767*fcf3ce44SJohn Forte {
768*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
769*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
770*fcf3ce44SJohn Forte 
771*fcf3ce44SJohn Forte 	bzero(parms, sizeof (dsw_config_t));
772*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "ii.set%d.master", setno);
773*fcf3ce44SJohn Forte 	if (cfg_get_cstring(cfg, key, parms->master_vol, DSW_NAMELEN) < 0)
774*fcf3ce44SJohn Forte 		return (-1);
775*fcf3ce44SJohn Forte 
776*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "ii.set%d.shadow", setno);
777*fcf3ce44SJohn Forte 	(void) cfg_get_cstring(cfg, key, parms->shadow_vol, DSW_NAMELEN);
778*fcf3ce44SJohn Forte 
779*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "ii.set%d.bitmap", setno);
780*fcf3ce44SJohn Forte 	(void) cfg_get_cstring(cfg, key, parms->bitmap_vol, DSW_NAMELEN);
781*fcf3ce44SJohn Forte 
782*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "ii.set%d.mode", setno);
783*fcf3ce44SJohn Forte 	(void) cfg_get_cstring(cfg, key, buf, sizeof (buf));
784*fcf3ce44SJohn Forte 	if (strcmp(buf, "I") == 0)
785*fcf3ce44SJohn Forte 		parms->flag |= DSW_GOLDEN;
786*fcf3ce44SJohn Forte 
787*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "ii.set%d.overflow", setno);
788*fcf3ce44SJohn Forte 	(void) cfg_get_cstring(cfg, key, last_overflow, DSW_NAMELEN);
789*fcf3ce44SJohn Forte 
790*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "ii.set%d.group", setno);
791*fcf3ce44SJohn Forte 	(void) cfg_get_cstring(cfg, key, parms->group_name, DSW_NAMELEN);
792*fcf3ce44SJohn Forte 
793*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "ii.set%d.cnode", setno);
794*fcf3ce44SJohn Forte 	(void) cfg_get_cstring(cfg, key, parms->cluster_tag, DSW_NAMELEN);
795*fcf3ce44SJohn Forte 	return (0);
796*fcf3ce44SJohn Forte }
797*fcf3ce44SJohn Forte 
798*fcf3ce44SJohn Forte static int
799*fcf3ce44SJohn Forte find_next_cf_line(char *volume, int next)
800*fcf3ce44SJohn Forte {
801*fcf3ce44SJohn Forte 	dsw_config_t cf_line;
802*fcf3ce44SJohn Forte 
803*fcf3ce44SJohn Forte 	for (setnumber = next; get_dsw_config(setnumber, &cf_line) == 0;
804*fcf3ce44SJohn Forte 								setnumber++) {
805*fcf3ce44SJohn Forte 		if (strncmp(volume, cf_line.master_vol, DSW_NAMELEN) == 0 ||
806*fcf3ce44SJohn Forte 		    strncmp(volume, cf_line.shadow_vol, DSW_NAMELEN) == 0 ||
807*fcf3ce44SJohn Forte 		    strncmp(volume, cf_line.bitmap_vol, DSW_NAMELEN) == 0)
808*fcf3ce44SJohn Forte 			return (1);
809*fcf3ce44SJohn Forte 	}
810*fcf3ce44SJohn Forte 	return (0);
811*fcf3ce44SJohn Forte }
812*fcf3ce44SJohn Forte int
813*fcf3ce44SJohn Forte find_any_cf_line(char *volume)
814*fcf3ce44SJohn Forte {
815*fcf3ce44SJohn Forte 	return (find_next_cf_line(volume, 1));
816*fcf3ce44SJohn Forte }
817*fcf3ce44SJohn Forte 
818*fcf3ce44SJohn Forte static int
819*fcf3ce44SJohn Forte find_next_shadow_line(char *volume, int next)
820*fcf3ce44SJohn Forte {
821*fcf3ce44SJohn Forte 	dsw_config_t cf_line;
822*fcf3ce44SJohn Forte 
823*fcf3ce44SJohn Forte 	for (setnumber = next; get_dsw_config(setnumber, &cf_line) == 0;
824*fcf3ce44SJohn Forte 	    setnumber++) {
825*fcf3ce44SJohn Forte 		if (strncmp(volume, cf_line.shadow_vol, DSW_NAMELEN) == 0)
826*fcf3ce44SJohn Forte 			return (1);
827*fcf3ce44SJohn Forte 	}
828*fcf3ce44SJohn Forte 	return (0);
829*fcf3ce44SJohn Forte }
830*fcf3ce44SJohn Forte int
831*fcf3ce44SJohn Forte find_shadow_line(char *volume)
832*fcf3ce44SJohn Forte {
833*fcf3ce44SJohn Forte 	return (find_next_shadow_line(volume, 1));
834*fcf3ce44SJohn Forte }
835*fcf3ce44SJohn Forte 
836*fcf3ce44SJohn Forte /*
837*fcf3ce44SJohn Forte  * this function is designed to be called once, subsequent calls won't
838*fcf3ce44SJohn Forte  * free memory allocated by earlier invocations.
839*fcf3ce44SJohn Forte  */
840*fcf3ce44SJohn Forte char *
841*fcf3ce44SJohn Forte get_overflow_list()
842*fcf3ce44SJohn Forte {
843*fcf3ce44SJohn Forte 	dsw_aioctl_t *acopy_args;
844*fcf3ce44SJohn Forte 	int rc, num;
845*fcf3ce44SJohn Forte 
846*fcf3ce44SJohn Forte 	num = do_ioctl(dsw_fd, DSWIOC_OLISTLEN, NULL);
847*fcf3ce44SJohn Forte 	if (num < 0)
848*fcf3ce44SJohn Forte 		dsw_error(gettext("Can't get overflow list length"), NULL);
849*fcf3ce44SJohn Forte 
850*fcf3ce44SJohn Forte 	acopy_args = malloc(sizeof (dsw_aioctl_t) + num * DSW_NAMELEN);
851*fcf3ce44SJohn Forte 	if (acopy_args == NULL)
852*fcf3ce44SJohn Forte 		dsw_error(gettext("Can't get memory for list enquiry"), NULL);
853*fcf3ce44SJohn Forte 
854*fcf3ce44SJohn Forte 	acopy_args->count = num;
855*fcf3ce44SJohn Forte 	acopy_args->flags = 0;
856*fcf3ce44SJohn Forte 	acopy_args->status = spcs_s_ucreate();
857*fcf3ce44SJohn Forte 
858*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_OLIST, acopy_args);
859*fcf3ce44SJohn Forte 	if (rc == -1)
860*fcf3ce44SJohn Forte 		dsw_error(gettext("Overflow list access failure"),
861*fcf3ce44SJohn Forte 			&acopy_args->status);
862*fcf3ce44SJohn Forte 	else
863*fcf3ce44SJohn Forte 		acopy_args->shadow_vol[DSW_NAMELEN*acopy_args->count] = NULL;
864*fcf3ce44SJohn Forte 
865*fcf3ce44SJohn Forte 	return (acopy_args->shadow_vol);
866*fcf3ce44SJohn Forte }
867*fcf3ce44SJohn Forte 
868*fcf3ce44SJohn Forte /*
869*fcf3ce44SJohn Forte  * this function is designed to be called once, subsequent calls won't
870*fcf3ce44SJohn Forte  * free memory allocated by earlier invocations.
871*fcf3ce44SJohn Forte  */
872*fcf3ce44SJohn Forte 
873*fcf3ce44SJohn Forte int
874*fcf3ce44SJohn Forte find_group_members(char *group)
875*fcf3ce44SJohn Forte {
876*fcf3ce44SJohn Forte 	int nmembers = 0;
877*fcf3ce44SJohn Forte 	int vector_len = 0;
878*fcf3ce44SJohn Forte 
879*fcf3ce44SJohn Forte 	group_volumes = NULL;
880*fcf3ce44SJohn Forte 	for (setnumber = 1; /*CSTYLED*/; setnumber++) {
881*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d.group", setnumber);
882*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf,
883*fcf3ce44SJohn Forte 					sizeof (buf)) < 0)
884*fcf3ce44SJohn Forte 			break;
885*fcf3ce44SJohn Forte 
886*fcf3ce44SJohn Forte 		if (strcmp(group, buf))
887*fcf3ce44SJohn Forte 			continue;
888*fcf3ce44SJohn Forte 
889*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d.shadow",
890*fcf3ce44SJohn Forte 		    setnumber);
891*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf,
892*fcf3ce44SJohn Forte 					sizeof (buf)) < 0)
893*fcf3ce44SJohn Forte 			break;
894*fcf3ce44SJohn Forte 
895*fcf3ce44SJohn Forte 		if (nmembers >= vector_len) {
896*fcf3ce44SJohn Forte 			vector_len += 10;
897*fcf3ce44SJohn Forte 			group_volumes = realloc(group_volumes, (1+vector_len) *
898*fcf3ce44SJohn Forte 					sizeof (char *));
899*fcf3ce44SJohn Forte 		}
900*fcf3ce44SJohn Forte 		group_volumes[nmembers] = strdup(buf);
901*fcf3ce44SJohn Forte 		nmembers++;
902*fcf3ce44SJohn Forte 	}
903*fcf3ce44SJohn Forte 	if (group_volumes)
904*fcf3ce44SJohn Forte 		group_volumes[nmembers] = NULL;	/* terminate list */
905*fcf3ce44SJohn Forte 	return (nmembers);
906*fcf3ce44SJohn Forte }
907*fcf3ce44SJohn Forte 
908*fcf3ce44SJohn Forte static int
909*fcf3ce44SJohn Forte find_next_matching_cf_line(
910*fcf3ce44SJohn Forte 	char *volume, dsw_config_t *conf, dsw_ioctl_t *io, int next)
911*fcf3ce44SJohn Forte {
912*fcf3ce44SJohn Forte 	dsw_config_t config;
913*fcf3ce44SJohn Forte 
914*fcf3ce44SJohn Forte 	if (!find_next_cf_line(volume, next)) {
915*fcf3ce44SJohn Forte 		return (0);
916*fcf3ce44SJohn Forte 	}
917*fcf3ce44SJohn Forte 
918*fcf3ce44SJohn Forte 	if (conf == NULL)
919*fcf3ce44SJohn Forte 		conf = &config;
920*fcf3ce44SJohn Forte 	(void) get_dsw_config(setnumber, conf);
921*fcf3ce44SJohn Forte 	if (io) {
922*fcf3ce44SJohn Forte 		strncpy(io->shadow_vol, conf->shadow_vol, DSW_NAMELEN);
923*fcf3ce44SJohn Forte 		io->shadow_vol[DSW_NAMELEN] = '\0';
924*fcf3ce44SJohn Forte 	}
925*fcf3ce44SJohn Forte 	return (1);
926*fcf3ce44SJohn Forte }
927*fcf3ce44SJohn Forte 
928*fcf3ce44SJohn Forte int
929*fcf3ce44SJohn Forte find_matching_cf_line(char *volume, dsw_config_t *conf, dsw_ioctl_t *io)
930*fcf3ce44SJohn Forte {
931*fcf3ce44SJohn Forte 	return (find_next_matching_cf_line(volume, conf, io, 1));
932*fcf3ce44SJohn Forte }
933*fcf3ce44SJohn Forte 
934*fcf3ce44SJohn Forte int
935*fcf3ce44SJohn Forte find_shadow_config(char *volume, dsw_config_t *conf, dsw_ioctl_t *io)
936*fcf3ce44SJohn Forte {
937*fcf3ce44SJohn Forte 	dsw_config_t *c, cf;
938*fcf3ce44SJohn Forte 
939*fcf3ce44SJohn Forte 	if (io) {
940*fcf3ce44SJohn Forte 		bzero(io, sizeof (dsw_ioctl_t));
941*fcf3ce44SJohn Forte 	}
942*fcf3ce44SJohn Forte 	c = conf ? conf : &cf;
943*fcf3ce44SJohn Forte 	setnumber = 1;
944*fcf3ce44SJohn Forte 	/* perform action for each line of the stored config file */
945*fcf3ce44SJohn Forte 	for ((void) snprintf(key, sizeof (key), "ii.set%d.shadow", setnumber);
946*fcf3ce44SJohn Forte 	    cfg_get_cstring(cfg, key, c->shadow_vol, DSW_NAMELEN) >= 0;
947*fcf3ce44SJohn Forte 	    (void) snprintf(key, sizeof (key), "ii.set%d.shadow",
948*fcf3ce44SJohn Forte 	    ++setnumber)) {
949*fcf3ce44SJohn Forte 		if (strncmp(volume, c->shadow_vol, DSW_NAMELEN) == 0) {
950*fcf3ce44SJohn Forte 			(void) get_dsw_config(setnumber, c);
951*fcf3ce44SJohn Forte 
952*fcf3ce44SJohn Forte 			if (check_resource_group(c->bitmap_vol)) {
953*fcf3ce44SJohn Forte 				setnumber = 0;
954*fcf3ce44SJohn Forte 				continue;
955*fcf3ce44SJohn Forte 			}
956*fcf3ce44SJohn Forte 
957*fcf3ce44SJohn Forte 			switch (check_cluster()) {
958*fcf3ce44SJohn Forte 			case II_CLUSTER:
959*fcf3ce44SJohn Forte 				if ((cfg_cluster_tag) &&
960*fcf3ce44SJohn Forte 				    (strcmp(cfg_cluster_tag, c->cluster_tag)))
961*fcf3ce44SJohn Forte 					continue;
962*fcf3ce44SJohn Forte 				break;
963*fcf3ce44SJohn Forte 			case II_CLUSTER_LCL:
964*fcf3ce44SJohn Forte 				if (strlen(c->cluster_tag))
965*fcf3ce44SJohn Forte 					continue;
966*fcf3ce44SJohn Forte 				break;
967*fcf3ce44SJohn Forte 			}
968*fcf3ce44SJohn Forte 
969*fcf3ce44SJohn Forte 			if (io) {
970*fcf3ce44SJohn Forte 				strncpy(io->shadow_vol, c->shadow_vol,
971*fcf3ce44SJohn Forte 								DSW_NAMELEN);
972*fcf3ce44SJohn Forte 				io->shadow_vol[DSW_NAMELEN] = '\0';
973*fcf3ce44SJohn Forte 			}
974*fcf3ce44SJohn Forte 			return (1);
975*fcf3ce44SJohn Forte 		}
976*fcf3ce44SJohn Forte 	}
977*fcf3ce44SJohn Forte 	return (0);
978*fcf3ce44SJohn Forte }
979*fcf3ce44SJohn Forte 
980*fcf3ce44SJohn Forte void
981*fcf3ce44SJohn Forte add_cfg_entry(dsw_config_t *parms)
982*fcf3ce44SJohn Forte {
983*fcf3ce44SJohn Forte 	/* insert the well-known fields first */
984*fcf3ce44SJohn Forte 	(void) snprintf(buf, sizeof (buf), "%s %s %s %s",
985*fcf3ce44SJohn Forte 	    parms->master_vol, parms->shadow_vol, parms->bitmap_vol,
986*fcf3ce44SJohn Forte 	    (parms->flag & DSW_GOLDEN) ? "I" : "D");
987*fcf3ce44SJohn Forte 
988*fcf3ce44SJohn Forte 	if (cfg_put_cstring(cfg, "ii", buf, strlen(buf)) >=  0) {
989*fcf3ce44SJohn Forte 		/* if we have a group name, add it */
990*fcf3ce44SJohn Forte 		if (group_name) {
991*fcf3ce44SJohn Forte 			if (find_any_cf_line(parms->shadow_vol)) {
992*fcf3ce44SJohn Forte 				(void) sprintf(buf, "ii.set%d.group",
993*fcf3ce44SJohn Forte 				    setnumber);
994*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, buf,
995*fcf3ce44SJohn Forte 					group_name, strlen(group_name)) < 0)
996*fcf3ce44SJohn Forte 					perror("cfg_put_cstring");
997*fcf3ce44SJohn Forte 			}
998*fcf3ce44SJohn Forte 			else
999*fcf3ce44SJohn Forte 				perror("cfg_location");
1000*fcf3ce44SJohn Forte 		}
1001*fcf3ce44SJohn Forte 
1002*fcf3ce44SJohn Forte 		/* commit the record */
1003*fcf3ce44SJohn Forte 		(void) cfg_commit(cfg);
1004*fcf3ce44SJohn Forte 	}
1005*fcf3ce44SJohn Forte 	else
1006*fcf3ce44SJohn Forte 		perror("cfg_put_string");
1007*fcf3ce44SJohn Forte }
1008*fcf3ce44SJohn Forte 
1009*fcf3ce44SJohn Forte void
1010*fcf3ce44SJohn Forte remove_iiset(int setno, char *shadow, int shd_exp)
1011*fcf3ce44SJohn Forte {
1012*fcf3ce44SJohn Forte 	mstcount_t *mdata;
1013*fcf3ce44SJohn Forte 	shdvol_t *sdata;
1014*fcf3ce44SJohn Forte 	char sn[CFG_MAX_BUF];
1015*fcf3ce44SJohn Forte 
1016*fcf3ce44SJohn Forte 	if (perform_autosv()) {
1017*fcf3ce44SJohn Forte 		if (volhash) {
1018*fcf3ce44SJohn Forte 			unload_ii_vols();
1019*fcf3ce44SJohn Forte 		}
1020*fcf3ce44SJohn Forte 		load_ii_vols(cfg);
1021*fcf3ce44SJohn Forte 		if (cfg_load_dsvols(cfg) < 0 || cfg_load_svols(cfg) < 0) {
1022*fcf3ce44SJohn Forte 			dsw_error(gettext("Unable to parse config file"), NULL);
1023*fcf3ce44SJohn Forte 		}
1024*fcf3ce44SJohn Forte 
1025*fcf3ce44SJohn Forte 		sdata = (shdvol_t *)nsc_lookup(volhash, shadow);
1026*fcf3ce44SJohn Forte 		if (sdata) {
1027*fcf3ce44SJohn Forte 			/*
1028*fcf3ce44SJohn Forte 			 * Handle the normal cases of disabling a set that is
1029*fcf3ce44SJohn Forte 			 * not an imported shadow volume
1030*fcf3ce44SJohn Forte 			 */
1031*fcf3ce44SJohn Forte 			if (strcmp(sdata->master, II_IMPORTED_SHADOW)) {
1032*fcf3ce44SJohn Forte 				/*
1033*fcf3ce44SJohn Forte 				 * Handle multiple-shadows of single master
1034*fcf3ce44SJohn Forte 				 */
1035*fcf3ce44SJohn Forte 				mdata = (mstcount_t *)
1036*fcf3ce44SJohn Forte 					nsc_lookup(volhash, sdata->master);
1037*fcf3ce44SJohn Forte 				if ((mdata) && (mdata->count == 1)) {
1038*fcf3ce44SJohn Forte 				    if (cfg_vol_disable(cfg, sdata->master,
1039*fcf3ce44SJohn Forte 					cfg_cluster_tag, "ii") < 0)
1040*fcf3ce44SJohn Forte 					    dsw_error(gettext(
1041*fcf3ce44SJohn Forte 						"SV disable of master failed"),
1042*fcf3ce44SJohn Forte 						NULL);
1043*fcf3ce44SJohn Forte 				}
1044*fcf3ce44SJohn Forte 			}
1045*fcf3ce44SJohn Forte 
1046*fcf3ce44SJohn Forte 			/*
1047*fcf3ce44SJohn Forte 			 * Handle disk group name of different shadow
1048*fcf3ce44SJohn Forte 			 */
1049*fcf3ce44SJohn Forte 			if (shd_exp) {
1050*fcf3ce44SJohn Forte 				/*
1051*fcf3ce44SJohn Forte 				 * If shadow is exported, then do nothing
1052*fcf3ce44SJohn Forte 				 */
1053*fcf3ce44SJohn Forte 				/*EMPTY*/;
1054*fcf3ce44SJohn Forte 			} else if (cfg_cluster_tag &&
1055*fcf3ce44SJohn Forte 				    strcmp(cfg_cluster_tag, "") &&
1056*fcf3ce44SJohn Forte 				    cfg_dgname(shadow, sn, sizeof (sn)) &&
1057*fcf3ce44SJohn Forte 				    strlen(sn) &&
1058*fcf3ce44SJohn Forte 				    strcmp(sn, cfg_cluster_tag)) {
1059*fcf3ce44SJohn Forte 					/* reload disk group volumes */
1060*fcf3ce44SJohn Forte 					cfg_resource(cfg, sn);
1061*fcf3ce44SJohn Forte 					cfg_unload_dsvols();
1062*fcf3ce44SJohn Forte 					cfg_unload_svols();
1063*fcf3ce44SJohn Forte 					(void) cfg_load_dsvols(cfg);
1064*fcf3ce44SJohn Forte 					(void) cfg_load_svols(cfg);
1065*fcf3ce44SJohn Forte 					if (cfg_vol_disable(cfg, shadow, sn,
1066*fcf3ce44SJohn Forte 					    "ii") < 0)
1067*fcf3ce44SJohn Forte 					    dsw_error(gettext(
1068*fcf3ce44SJohn Forte 						"SV disable of shadow failed"),
1069*fcf3ce44SJohn Forte 						NULL);
1070*fcf3ce44SJohn Forte 					cfg_resource(cfg, cfg_cluster_tag);
1071*fcf3ce44SJohn Forte 			} else {
1072*fcf3ce44SJohn Forte 				if (cfg_vol_disable(cfg, shadow,
1073*fcf3ce44SJohn Forte 				    cfg_cluster_tag, "ii") < 0)
1074*fcf3ce44SJohn Forte 					dsw_error(gettext(
1075*fcf3ce44SJohn Forte 					    "SV disable of shadow failed"),
1076*fcf3ce44SJohn Forte 					    NULL);
1077*fcf3ce44SJohn Forte 			}
1078*fcf3ce44SJohn Forte 		}
1079*fcf3ce44SJohn Forte 		cfg_unload_svols();
1080*fcf3ce44SJohn Forte 		cfg_unload_dsvols();
1081*fcf3ce44SJohn Forte 		unload_ii_vols();
1082*fcf3ce44SJohn Forte 		reload_vols &= ~(LD_SVOLS | LD_DSVOLS | LD_II);
1083*fcf3ce44SJohn Forte 	}
1084*fcf3ce44SJohn Forte 
1085*fcf3ce44SJohn Forte 	(void) sprintf(key, "ii.set%d", setno);
1086*fcf3ce44SJohn Forte 	if (cfg_put_cstring(cfg, key, NULL, 0) < 0) {
1087*fcf3ce44SJohn Forte 		perror("cfg_put_cstring");
1088*fcf3ce44SJohn Forte 	}
1089*fcf3ce44SJohn Forte 	(void) cfg_commit(cfg);
1090*fcf3ce44SJohn Forte }
1091*fcf3ce44SJohn Forte 
1092*fcf3ce44SJohn Forte /*
1093*fcf3ce44SJohn Forte  * determine if we are running in a Sun Cluster Environment
1094*fcf3ce44SJohn Forte  */
1095*fcf3ce44SJohn Forte int
1096*fcf3ce44SJohn Forte check_cluster()
1097*fcf3ce44SJohn Forte {
1098*fcf3ce44SJohn Forte 	static int is_cluster = -1;
1099*fcf3ce44SJohn Forte 	int rc;
1100*fcf3ce44SJohn Forte #ifdef DEBUG
1101*fcf3ce44SJohn Forte 	char *cdebug = getenv("II_SET_CLUSTER");
1102*fcf3ce44SJohn Forte #endif
1103*fcf3ce44SJohn Forte 
1104*fcf3ce44SJohn Forte 	/*
1105*fcf3ce44SJohn Forte 	 * If this routine was previously called, just return results
1106*fcf3ce44SJohn Forte 	 */
1107*fcf3ce44SJohn Forte 	if (is_cluster != -1)
1108*fcf3ce44SJohn Forte 		return (is_cluster);
1109*fcf3ce44SJohn Forte 
1110*fcf3ce44SJohn Forte 	/*
1111*fcf3ce44SJohn Forte 	 * See if Sun Cluster was installed on this node
1112*fcf3ce44SJohn Forte 	 */
1113*fcf3ce44SJohn Forte #ifdef DEBUG
1114*fcf3ce44SJohn Forte 	if (cdebug) rc = atoi(cdebug);
1115*fcf3ce44SJohn Forte 	else
1116*fcf3ce44SJohn Forte #endif
1117*fcf3ce44SJohn Forte 	rc = cfg_iscluster();
1118*fcf3ce44SJohn Forte 	if (rc > 0) {
1119*fcf3ce44SJohn Forte 		/*
1120*fcf3ce44SJohn Forte 		 * Determine if user specified -C local
1121*fcf3ce44SJohn Forte 		 */
1122*fcf3ce44SJohn Forte 		if ((cfg_cluster_tag == NULL) ||
1123*fcf3ce44SJohn Forte 		    (strcmp(cfg_cluster_tag, II_LOCAL_TAG))) {
1124*fcf3ce44SJohn Forte 			/*
1125*fcf3ce44SJohn Forte 			 * We're in a Sun Cluster, and no "-C local"
1126*fcf3ce44SJohn Forte 			 */
1127*fcf3ce44SJohn Forte 			is_cluster = II_CLUSTER;
1128*fcf3ce44SJohn Forte 		} else {
1129*fcf3ce44SJohn Forte 			/*
1130*fcf3ce44SJohn Forte 			 * We're in a Sun Cluster, but "-C local" was specified
1131*fcf3ce44SJohn Forte 			 */
1132*fcf3ce44SJohn Forte 			is_cluster = II_CLUSTER_LCL;
1133*fcf3ce44SJohn Forte 			cfg_cluster_tag = "";
1134*fcf3ce44SJohn Forte 		}
1135*fcf3ce44SJohn Forte 		return (is_cluster);
1136*fcf3ce44SJohn Forte 	} else if (rc == 0) {
1137*fcf3ce44SJohn Forte 		/*
1138*fcf3ce44SJohn Forte 		 * Not in a Sun Cluster
1139*fcf3ce44SJohn Forte 		 */
1140*fcf3ce44SJohn Forte 		is_cluster = II_NOT_CLUSTER;
1141*fcf3ce44SJohn Forte 		return (is_cluster);
1142*fcf3ce44SJohn Forte 	} else {
1143*fcf3ce44SJohn Forte 		dsw_error(gettext("unable to ascertain environment"), NULL);
1144*fcf3ce44SJohn Forte 		/*NOTREACHED*/
1145*fcf3ce44SJohn Forte 	}
1146*fcf3ce44SJohn Forte 
1147*fcf3ce44SJohn Forte 	/* gcc */
1148*fcf3ce44SJohn Forte 	return (is_cluster);
1149*fcf3ce44SJohn Forte }
1150*fcf3ce44SJohn Forte 
1151*fcf3ce44SJohn Forte /*
1152*fcf3ce44SJohn Forte  * Determine if we need to set a cfg_resource based on this volume
1153*fcf3ce44SJohn Forte  */
1154*fcf3ce44SJohn Forte static int
1155*fcf3ce44SJohn Forte check_resource_group(char *volume)
1156*fcf3ce44SJohn Forte {
1157*fcf3ce44SJohn Forte 	char diskgroup[CFG_MAX_BUF];
1158*fcf3ce44SJohn Forte 
1159*fcf3ce44SJohn Forte 	/*
1160*fcf3ce44SJohn Forte 	 * If we are in a cluster, attempt to derive a new resource group
1161*fcf3ce44SJohn Forte 	 */
1162*fcf3ce44SJohn Forte 
1163*fcf3ce44SJohn Forte #ifdef DEBUG
1164*fcf3ce44SJohn Forte 	if (getenv("II_SET_CLUSTER") || (check_cluster() == II_CLUSTER)) {
1165*fcf3ce44SJohn Forte #else
1166*fcf3ce44SJohn Forte 	if (check_cluster() == II_CLUSTER) {
1167*fcf3ce44SJohn Forte #endif
1168*fcf3ce44SJohn Forte 		if (check_diskgroup(volume, diskgroup)) {
1169*fcf3ce44SJohn Forte 			if (cfg_cluster_tag == NULL) {
1170*fcf3ce44SJohn Forte 				cfg_cluster_tag = strdup(diskgroup);
1171*fcf3ce44SJohn Forte 				if (cfg_cluster_tag == NULL)
1172*fcf3ce44SJohn Forte 					dsw_error(gettext(
1173*fcf3ce44SJohn Forte 					"Memory allocation failure"), NULL);
1174*fcf3ce44SJohn Forte 				cfg_resource(cfg, cfg_cluster_tag);
1175*fcf3ce44SJohn Forte 				return (1);
1176*fcf3ce44SJohn Forte 			} else {
1177*fcf3ce44SJohn Forte 			/*
1178*fcf3ce44SJohn Forte 			 * Check dgname and cluster tag from -C are the same.
1179*fcf3ce44SJohn Forte 			 */
1180*fcf3ce44SJohn Forte 			if (strcmp(diskgroup, cfg_cluster_tag) != 0) {
1181*fcf3ce44SJohn Forte 			    char error_buffer[128];
1182*fcf3ce44SJohn Forte 			    (void) snprintf(error_buffer, sizeof (error_buffer),
1183*fcf3ce44SJohn Forte 				gettext(
1184*fcf3ce44SJohn Forte 				    "-C (%s) does not match disk group "
1185*fcf3ce44SJohn Forte 				    "name (%s) for %s"), cfg_cluster_tag,
1186*fcf3ce44SJohn Forte 				    diskgroup, volume);
1187*fcf3ce44SJohn Forte 				spcs_log("ii", NULL, error_buffer);
1188*fcf3ce44SJohn Forte 				dsw_error(error_buffer, NULL);
1189*fcf3ce44SJohn Forte 			    }
1190*fcf3ce44SJohn Forte 			}
1191*fcf3ce44SJohn Forte 		} else if (cfg_cluster_tag == NULL)
1192*fcf3ce44SJohn Forte 			dsw_error(gettext(
1193*fcf3ce44SJohn Forte 				"Point-in-Time Copy volumes, that are not "
1194*fcf3ce44SJohn Forte 				"in a device group which has been "
1195*fcf3ce44SJohn Forte 				"registered with SunCluster, "
1196*fcf3ce44SJohn Forte 				"require usage of \"-C\""), NULL);
1197*fcf3ce44SJohn Forte 	}
1198*fcf3ce44SJohn Forte 	return (0);
1199*fcf3ce44SJohn Forte }
1200*fcf3ce44SJohn Forte 
1201*fcf3ce44SJohn Forte static void
1202*fcf3ce44SJohn Forte check_dg_is_local(char *dgname)
1203*fcf3ce44SJohn Forte {
1204*fcf3ce44SJohn Forte 	char error_buffer[128];
1205*fcf3ce44SJohn Forte 	char *othernode;
1206*fcf3ce44SJohn Forte 	int rc;
1207*fcf3ce44SJohn Forte 
1208*fcf3ce44SJohn Forte 	/*
1209*fcf3ce44SJohn Forte 	 * check where this disk service is mastered
1210*fcf3ce44SJohn Forte 	 */
1211*fcf3ce44SJohn Forte 	rc = cfg_dgname_islocal(dgname, &othernode);
1212*fcf3ce44SJohn Forte 	if (rc < 0) {
1213*fcf3ce44SJohn Forte 		(void) snprintf(error_buffer, sizeof (error_buffer),
1214*fcf3ce44SJohn Forte 		    gettext("Unable to find disk service:%s"), dgname);
1215*fcf3ce44SJohn Forte 		dsw_error(error_buffer, NULL);
1216*fcf3ce44SJohn Forte 	} else if (rc == 0) {
1217*fcf3ce44SJohn Forte 		(void) snprintf(error_buffer, sizeof (error_buffer),
1218*fcf3ce44SJohn Forte 		    gettext("disk service, %s, is active on node \"%s\"\n"
1219*fcf3ce44SJohn Forte 		    "Please re-issue the command on that node"), dgname,
1220*fcf3ce44SJohn Forte 		    othernode);
1221*fcf3ce44SJohn Forte 		dsw_error(error_buffer, NULL);
1222*fcf3ce44SJohn Forte 	}
1223*fcf3ce44SJohn Forte }
1224*fcf3ce44SJohn Forte 
1225*fcf3ce44SJohn Forte /*
1226*fcf3ce44SJohn Forte  * Carry out cluster based checks for a specified volume, or just
1227*fcf3ce44SJohn Forte  * global options.
1228*fcf3ce44SJohn Forte  */
1229*fcf3ce44SJohn Forte static int
1230*fcf3ce44SJohn Forte check_diskgroup(char *path, char *result)
1231*fcf3ce44SJohn Forte {
1232*fcf3ce44SJohn Forte 	char dgname[CFG_MAX_BUF];
1233*fcf3ce44SJohn Forte 	char error_buffer[128];
1234*fcf3ce44SJohn Forte 
1235*fcf3ce44SJohn Forte #ifdef DEBUG
1236*fcf3ce44SJohn Forte 	char *override = getenv("II_CLUSTER_TAG");
1237*fcf3ce44SJohn Forte 	if (override) {
1238*fcf3ce44SJohn Forte 		strcpy(result, override);
1239*fcf3ce44SJohn Forte 		return (1);
1240*fcf3ce44SJohn Forte 	}
1241*fcf3ce44SJohn Forte #endif
1242*fcf3ce44SJohn Forte 	/*
1243*fcf3ce44SJohn Forte 	 * Check on path name, a returned NULL dgname is valid
1244*fcf3ce44SJohn Forte 	 */
1245*fcf3ce44SJohn Forte 	if (cfg_dgname(path, dgname, sizeof (dgname)) == NULL) {
1246*fcf3ce44SJohn Forte 		(void) snprintf(error_buffer, sizeof (error_buffer), gettext(
1247*fcf3ce44SJohn Forte 		    "unable to determine disk group name for %s"), path);
1248*fcf3ce44SJohn Forte 		dsw_error(error_buffer, NULL);
1249*fcf3ce44SJohn Forte 	}
1250*fcf3ce44SJohn Forte 	if (strcmp(dgname, "") == 0)
1251*fcf3ce44SJohn Forte 		return (0);
1252*fcf3ce44SJohn Forte 
1253*fcf3ce44SJohn Forte 	/*
1254*fcf3ce44SJohn Forte 	 * See if disk group is local to this node
1255*fcf3ce44SJohn Forte 	 */
1256*fcf3ce44SJohn Forte 	check_dg_is_local(dgname);
1257*fcf3ce44SJohn Forte 
1258*fcf3ce44SJohn Forte 	/*
1259*fcf3ce44SJohn Forte 	 * Copy dgname into result
1260*fcf3ce44SJohn Forte 	 */
1261*fcf3ce44SJohn Forte 	strcpy(result, dgname);
1262*fcf3ce44SJohn Forte 	return (1);
1263*fcf3ce44SJohn Forte }
1264*fcf3ce44SJohn Forte 
1265*fcf3ce44SJohn Forte /*
1266*fcf3ce44SJohn Forte  * sigterm (): traps specified signal , usually termination one
1267*fcf3ce44SJohn Forte  */
1268*fcf3ce44SJohn Forte void
1269*fcf3ce44SJohn Forte sigterm(int sig)
1270*fcf3ce44SJohn Forte {
1271*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("%s received signal %d"), cmdnam, sig);
1272*fcf3ce44SJohn Forte 	exit(1);
1273*fcf3ce44SJohn Forte }
1274*fcf3ce44SJohn Forte 
1275*fcf3ce44SJohn Forte /*
1276*fcf3ce44SJohn Forte  * sigchild; reap child and collect status.
1277*fcf3ce44SJohn Forte  */
1278*fcf3ce44SJohn Forte 
1279*fcf3ce44SJohn Forte volatile pid_t	dead_child;
1280*fcf3ce44SJohn Forte int	dead_stat;
1281*fcf3ce44SJohn Forte 
1282*fcf3ce44SJohn Forte /*ARGSUSED*/
1283*fcf3ce44SJohn Forte void
1284*fcf3ce44SJohn Forte sigchild(int sig)
1285*fcf3ce44SJohn Forte {
1286*fcf3ce44SJohn Forte 	dead_child = wait(&dead_stat);
1287*fcf3ce44SJohn Forte }
1288*fcf3ce44SJohn Forte 
1289*fcf3ce44SJohn Forte /*
1290*fcf3ce44SJohn Forte  * InitEnv(): initializes environment
1291*fcf3ce44SJohn Forte  */
1292*fcf3ce44SJohn Forte void
1293*fcf3ce44SJohn Forte InitEnv()
1294*fcf3ce44SJohn Forte {
1295*fcf3ce44SJohn Forte 	(void) setlocale(LC_ALL, "");
1296*fcf3ce44SJohn Forte 	(void) textdomain(DSW_TEXT_DOMAIN);
1297*fcf3ce44SJohn Forte 
1298*fcf3ce44SJohn Forte #ifndef DEBUG
1299*fcf3ce44SJohn Forte 	sigset(SIGHUP, sigterm);
1300*fcf3ce44SJohn Forte 	sigset(SIGINT, sigterm);
1301*fcf3ce44SJohn Forte 	sigset(SIGQUIT, sigterm);
1302*fcf3ce44SJohn Forte 	sigset(SIGILL, sigterm);
1303*fcf3ce44SJohn Forte 	sigset(SIGEMT, sigterm);
1304*fcf3ce44SJohn Forte 	sigset(SIGABRT, sigterm);
1305*fcf3ce44SJohn Forte 	sigset(SIGFPE, sigterm);
1306*fcf3ce44SJohn Forte 	sigset(SIGBUS, sigterm);
1307*fcf3ce44SJohn Forte 	sigset(SIGSEGV, sigterm);
1308*fcf3ce44SJohn Forte 	sigset(SIGTERM, sigterm);
1309*fcf3ce44SJohn Forte 	sigset(SIGPWR, sigterm);
1310*fcf3ce44SJohn Forte 	sigset(SIGSTOP, sigterm);
1311*fcf3ce44SJohn Forte 	sigset(SIGTSTP, sigterm);
1312*fcf3ce44SJohn Forte #endif
1313*fcf3ce44SJohn Forte 
1314*fcf3ce44SJohn Forte 	dsw_fd = open(DSWDEV, O_RDONLY);
1315*fcf3ce44SJohn Forte 	if (dsw_fd < 0) {
1316*fcf3ce44SJohn Forte 		perror(DSWDEV);
1317*fcf3ce44SJohn Forte 		exit(1);
1318*fcf3ce44SJohn Forte 	}
1319*fcf3ce44SJohn Forte 
1320*fcf3ce44SJohn Forte 	setsid();
1321*fcf3ce44SJohn Forte }
1322*fcf3ce44SJohn Forte 
1323*fcf3ce44SJohn Forte /*
1324*fcf3ce44SJohn Forte  * print an error message, followed by decoded errno then exit.
1325*fcf3ce44SJohn Forte  */
1326*fcf3ce44SJohn Forte void
1327*fcf3ce44SJohn Forte dsw_error(char *str, spcs_s_info_t *status)
1328*fcf3ce44SJohn Forte {
1329*fcf3ce44SJohn Forte 	char *sp;
1330*fcf3ce44SJohn Forte 
1331*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "%s: %s:\n", cmdnam, str);
1332*fcf3ce44SJohn Forte 	if (status == NULL) {
1333*fcf3ce44SJohn Forte 		/* deflect ESRCH */
1334*fcf3ce44SJohn Forte 		if (ESRCH == errno) {
1335*fcf3ce44SJohn Forte 			sp = "Set/volume not found";
1336*fcf3ce44SJohn Forte 		} else {
1337*fcf3ce44SJohn Forte 			sp = strerror(errno);
1338*fcf3ce44SJohn Forte 		}
1339*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n", sp ? sp : "");
1340*fcf3ce44SJohn Forte 	} else {
1341*fcf3ce44SJohn Forte 		spcs_s_report(*status, stderr);
1342*fcf3ce44SJohn Forte 		spcs_s_ufree(status);
1343*fcf3ce44SJohn Forte 	}
1344*fcf3ce44SJohn Forte 	if (cfg)
1345*fcf3ce44SJohn Forte 		cfg_close(cfg);
1346*fcf3ce44SJohn Forte 	exit(2);
1347*fcf3ce44SJohn Forte }
1348*fcf3ce44SJohn Forte 
1349*fcf3ce44SJohn Forte 
1350*fcf3ce44SJohn Forte #undef size
1351*fcf3ce44SJohn Forte 
1352*fcf3ce44SJohn Forte void
1353*fcf3ce44SJohn Forte free_bitmap(unsigned char *bitmap)
1354*fcf3ce44SJohn Forte {
1355*fcf3ce44SJohn Forte 	free(bitmap);
1356*fcf3ce44SJohn Forte }
1357*fcf3ce44SJohn Forte 
1358*fcf3ce44SJohn Forte 
1359*fcf3ce44SJohn Forte int
1360*fcf3ce44SJohn Forte get_bitmap(master_volume, shd_bitmap, copy_bitmap, size)
1361*fcf3ce44SJohn Forte 	char		*master_volume;
1362*fcf3ce44SJohn Forte 	unsigned char	*shd_bitmap;
1363*fcf3ce44SJohn Forte 	unsigned char	*copy_bitmap;
1364*fcf3ce44SJohn Forte 	unsigned long	size;
1365*fcf3ce44SJohn Forte {
1366*fcf3ce44SJohn Forte 	dsw_bitmap_t parms;
1367*fcf3ce44SJohn Forte 
1368*fcf3ce44SJohn Forte 	strncpy(parms.shadow_vol, master_volume, DSW_NAMELEN);
1369*fcf3ce44SJohn Forte 	parms.shadow_vol[DSW_NAMELEN-1] = '\0';
1370*fcf3ce44SJohn Forte 	parms.shd_bitmap = shd_bitmap;
1371*fcf3ce44SJohn Forte 	parms.shd_size = size;
1372*fcf3ce44SJohn Forte 	parms.copy_bitmap = copy_bitmap;
1373*fcf3ce44SJohn Forte 	parms.copy_size = size;
1374*fcf3ce44SJohn Forte 
1375*fcf3ce44SJohn Forte 	return (do_ioctl(dsw_fd, DSWIOC_BITMAP, &parms));
1376*fcf3ce44SJohn Forte }
1377*fcf3ce44SJohn Forte 
1378*fcf3ce44SJohn Forte unsigned char *
1379*fcf3ce44SJohn Forte allocate_bitmap(char *shadow_volume)
1380*fcf3ce44SJohn Forte {
1381*fcf3ce44SJohn Forte 	unsigned char	*shd_bitmap;
1382*fcf3ce44SJohn Forte 	unsigned char	*copy_bitmap;
1383*fcf3ce44SJohn Forte 	unsigned char	*p;
1384*fcf3ce44SJohn Forte 	unsigned char	*q;
1385*fcf3ce44SJohn Forte 	int		i;
1386*fcf3ce44SJohn Forte 	dsw_stat_t	args;
1387*fcf3ce44SJohn Forte 	int		stat_flags;
1388*fcf3ce44SJohn Forte 
1389*fcf3ce44SJohn Forte 	strncpy(args.shadow_vol, shadow_volume, DSW_NAMELEN);
1390*fcf3ce44SJohn Forte 	args.shadow_vol[DSW_NAMELEN-1] = '\0';
1391*fcf3ce44SJohn Forte 
1392*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
1393*fcf3ce44SJohn Forte 	if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1)
1394*fcf3ce44SJohn Forte 		dsw_error(gettext("Stat failed"), &args.status);
1395*fcf3ce44SJohn Forte 
1396*fcf3ce44SJohn Forte 	stat_flags = args.stat;
1397*fcf3ce44SJohn Forte 	if (stat_flags & DSW_BMPOFFLINE)
1398*fcf3ce44SJohn Forte 		return (NULL);
1399*fcf3ce44SJohn Forte 
1400*fcf3ce44SJohn Forte 	bm_size = args.size;
1401*fcf3ce44SJohn Forte 	bm_size = (bm_size + DSW_SIZE-1) / DSW_SIZE;
1402*fcf3ce44SJohn Forte 	bm_actual = bm_size;
1403*fcf3ce44SJohn Forte 	bm_size = (bm_size + DSW_BITS-1) / DSW_BITS;
1404*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
1405*fcf3ce44SJohn Forte 
1406*fcf3ce44SJohn Forte 	p = shd_bitmap = (unsigned char *) malloc(bm_size);
1407*fcf3ce44SJohn Forte 	if (!shd_bitmap) {
1408*fcf3ce44SJohn Forte 		perror(gettext("malloc bitmap"));
1409*fcf3ce44SJohn Forte 		return (NULL);
1410*fcf3ce44SJohn Forte 	}
1411*fcf3ce44SJohn Forte 
1412*fcf3ce44SJohn Forte 	q = copy_bitmap = (unsigned char *) malloc(bm_size);
1413*fcf3ce44SJohn Forte 	if (!copy_bitmap) {
1414*fcf3ce44SJohn Forte 		perror(gettext("malloc bitmap"));
1415*fcf3ce44SJohn Forte 		free(shd_bitmap);
1416*fcf3ce44SJohn Forte 		return (NULL);
1417*fcf3ce44SJohn Forte 	}
1418*fcf3ce44SJohn Forte 
1419*fcf3ce44SJohn Forte 	memset(shd_bitmap, 0, bm_size);
1420*fcf3ce44SJohn Forte 	memset(copy_bitmap, 0, bm_size);
1421*fcf3ce44SJohn Forte 
1422*fcf3ce44SJohn Forte 	if (get_bitmap(shadow_volume, shd_bitmap, copy_bitmap, bm_size) < 0) {
1423*fcf3ce44SJohn Forte 		free(copy_bitmap);
1424*fcf3ce44SJohn Forte 		free(shd_bitmap);
1425*fcf3ce44SJohn Forte 		return (NULL);
1426*fcf3ce44SJohn Forte 	}
1427*fcf3ce44SJohn Forte 
1428*fcf3ce44SJohn Forte 	/*
1429*fcf3ce44SJohn Forte 	 * "or" the copy and shadow bitmaps together to return a composite
1430*fcf3ce44SJohn Forte 	 * bitmap that contains the total set of differences between the
1431*fcf3ce44SJohn Forte 	 * volumes.
1432*fcf3ce44SJohn Forte 	 */
1433*fcf3ce44SJohn Forte 	for (i = bm_size; i-- > 0; /*CSTYLED*/)
1434*fcf3ce44SJohn Forte 		*p++ |= *q++;
1435*fcf3ce44SJohn Forte 
1436*fcf3ce44SJohn Forte 	free(copy_bitmap);
1437*fcf3ce44SJohn Forte 
1438*fcf3ce44SJohn Forte 	return (shd_bitmap);
1439*fcf3ce44SJohn Forte }
1440*fcf3ce44SJohn Forte 
1441*fcf3ce44SJohn Forte /*
1442*fcf3ce44SJohn Forte  * print usage message and exit.
1443*fcf3ce44SJohn Forte  */
1444*fcf3ce44SJohn Forte void
1445*fcf3ce44SJohn Forte usage(char *why)
1446*fcf3ce44SJohn Forte {
1447*fcf3ce44SJohn Forte 	if (why) {
1448*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s: %s\n", cmdnam, why);
1449*fcf3ce44SJohn Forte 
1450*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1451*fcf3ce44SJohn Forte 		    gettext("\nBrief summary:"));
1452*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1453*fcf3ce44SJohn Forte 		    gettext("\t-e {ind|dep} master_vol shadow_vol "
1454*fcf3ce44SJohn Forte 		    "bitmap_vol"));
1455*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1456*fcf3ce44SJohn Forte 		    gettext("\t-[cu {s|m}] volume_set"));
1457*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1458*fcf3ce44SJohn Forte 		    gettext("\t-i all"));
1459*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1460*fcf3ce44SJohn Forte 		    gettext("\t-[adDEilPRw] volume_set"));
1461*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1462*fcf3ce44SJohn Forte 		    gettext("\t-g group_name [options]"));
1463*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1464*fcf3ce44SJohn Forte 		    gettext("\t-C cluster_tag [options]"));
1465*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1466*fcf3ce44SJohn Forte 		    gettext("\t-[hilLv]"));
1467*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1468*fcf3ce44SJohn Forte 		    gettext("\t-[IJ] volume_set bitmap"));
1469*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1470*fcf3ce44SJohn Forte 		    gettext("\t-A overflow_vol volume_set"));
1471*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1472*fcf3ce44SJohn Forte 		    gettext("\t-[OQ] overflow_vol"));
1473*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s\n",
1474*fcf3ce44SJohn Forte 		    gettext("\t-P {delay} {units} volume_set"));
1475*fcf3ce44SJohn Forte 
1476*fcf3ce44SJohn Forte 		/* assume we came here due to a user mistake */
1477*fcf3ce44SJohn Forte 		exit(1);
1478*fcf3ce44SJohn Forte 		/* NOTREACHED */
1479*fcf3ce44SJohn Forte 	} else {
1480*fcf3ce44SJohn Forte 
1481*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1482*fcf3ce44SJohn Forte 		    gettext("Point-in-Time Copy Administrator CLI options"));
1483*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1484*fcf3ce44SJohn Forte 		    gettext("Usage summary:"));
1485*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1486*fcf3ce44SJohn Forte 		    gettext("\t-e ind m s b\tenable independent master shadow "
1487*fcf3ce44SJohn Forte 		    "bitmap"));
1488*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1489*fcf3ce44SJohn Forte 		    gettext("\t-e dep m s b\tenable dependent master shadow "
1490*fcf3ce44SJohn Forte 		    "bitmap"));
1491*fcf3ce44SJohn Forte 		if (check_cluster() == II_CLUSTER)
1492*fcf3ce44SJohn Forte 		    (void) fprintf(stdout, "%s\n",
1493*fcf3ce44SJohn Forte 			gettext("\t-ne ind m s b\tenable exportable master "
1494*fcf3ce44SJohn Forte 			"shadow bitmap"));
1495*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1496*fcf3ce44SJohn Forte 		    gettext("\t-d v\t\tdisable volume"));
1497*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1498*fcf3ce44SJohn Forte 		    gettext("\t-u s v\t\tupdate shadow volume"));
1499*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1500*fcf3ce44SJohn Forte 		    gettext("\t-u m v\t\tupdate master volume"));
1501*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1502*fcf3ce44SJohn Forte 		    gettext("\t-c s v\t\tcopy to shadow volume"));
1503*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1504*fcf3ce44SJohn Forte 		    gettext("\t-c m v\t\tcopy to master volume"));
1505*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1506*fcf3ce44SJohn Forte 		    gettext("\t-a v\t\tabort copy volume"));
1507*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1508*fcf3ce44SJohn Forte 		    gettext("\t-w v\t\twait volume"));
1509*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1510*fcf3ce44SJohn Forte 		    gettext("\t-i v\t\tdisplay volume status"));
1511*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1512*fcf3ce44SJohn Forte 		    gettext("\t-i all\t\tdisplay all volume status"));
1513*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1514*fcf3ce44SJohn Forte 		    gettext("\t-l\t\tlist all volumes"));
1515*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1516*fcf3ce44SJohn Forte 		    gettext("\t-R v\t\treset volume"));
1517*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1518*fcf3ce44SJohn Forte 		    gettext("\t-A o v\t\tattach overflow to volume"));
1519*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1520*fcf3ce44SJohn Forte 		    gettext("\t-D v\t\tdetach overflow from volume"));
1521*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1522*fcf3ce44SJohn Forte 		    gettext("\t-L\t\tlist all overflow volumes"));
1523*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1524*fcf3ce44SJohn Forte 		    gettext("\t-O o\t\tinitialize overflow"));
1525*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1526*fcf3ce44SJohn Forte 		    gettext("\t-Q o\t\tquery status of overflow"));
1527*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1528*fcf3ce44SJohn Forte 		    gettext("\t-E v\t\texport shadow volume"));
1529*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1530*fcf3ce44SJohn Forte 		    gettext("\t-I v b\t\timport volume bitmap"));
1531*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1532*fcf3ce44SJohn Forte 		    gettext("\t-J v b\t\tjoin volume bitmap"));
1533*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1534*fcf3ce44SJohn Forte 		    gettext("\t-P d u v\tset copy delay/units for volume"));
1535*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1536*fcf3ce44SJohn Forte 		    gettext("\t-P v\t\tget copy delay/units for volume"));
1537*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1538*fcf3ce44SJohn Forte 		    gettext("\t-C tag\t\tcluster resource tag"));
1539*fcf3ce44SJohn Forte #ifdef DEBUG
1540*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1541*fcf3ce44SJohn Forte 		    gettext("\t-b v\t\tdisplay bitmap volume"));
1542*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1543*fcf3ce44SJohn Forte 		    gettext("\t-f f\t\tuse private configuration file"));
1544*fcf3ce44SJohn Forte #endif
1545*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1546*fcf3ce44SJohn Forte 		    gettext("\t-v\t\tprint software versions"));
1547*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1548*fcf3ce44SJohn Forte 		    gettext("\t-n\t\tperform action without question"));
1549*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1550*fcf3ce44SJohn Forte 		    gettext("\t-p [-c|-u] {m|s}"
1551*fcf3ce44SJohn Forte 			"enable PID locking on copy or update"));
1552*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1553*fcf3ce44SJohn Forte 		    gettext("\t-p -w v\t\tdisable PID locking"));
1554*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1555*fcf3ce44SJohn Forte 		    gettext("\t-h\t\tiiadm usage summary"));
1556*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1557*fcf3ce44SJohn Forte 		    gettext("\nUsage summary for options that support "
1558*fcf3ce44SJohn Forte 		    "grouping (-g g):"));
1559*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1560*fcf3ce44SJohn Forte 		    gettext("\t-g g -e ind m s b group enable independent "
1561*fcf3ce44SJohn Forte 		    "master shadow bitmap"));
1562*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1563*fcf3ce44SJohn Forte 		    gettext("\t-g g -e dep m s b group enable dependent "
1564*fcf3ce44SJohn Forte 		    "master shadow bitmap"));
1565*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1566*fcf3ce44SJohn Forte 		    gettext("\t-g g -d\t\tdisable group"));
1567*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1568*fcf3ce44SJohn Forte 		    gettext("\t-g g -u s\tupdate shadow for all volumes in "
1569*fcf3ce44SJohn Forte 		    "group"));
1570*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1571*fcf3ce44SJohn Forte 		    gettext("\t-g g -u m\tupdate master for all volumes in "
1572*fcf3ce44SJohn Forte 		    "group"));
1573*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1574*fcf3ce44SJohn Forte 		    gettext("\t-g g -c s\tcopy to shadow for all volumes in "
1575*fcf3ce44SJohn Forte 		    "group"));
1576*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1577*fcf3ce44SJohn Forte 		    gettext("\t-g g -c m\tcopy to master for all volumes in "
1578*fcf3ce44SJohn Forte 		    "group"));
1579*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1580*fcf3ce44SJohn Forte 		    gettext("\t-g g -a\t\tabort copy for all volumes in "
1581*fcf3ce44SJohn Forte 		    "group"));
1582*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1583*fcf3ce44SJohn Forte 		    gettext("\t-g g -w\t\twait for all volumes in group"));
1584*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1585*fcf3ce44SJohn Forte 		    gettext("\t-g g -i\t\tdisplay status of all volumes in "
1586*fcf3ce44SJohn Forte 		    "group"));
1587*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1588*fcf3ce44SJohn Forte 		    gettext("\t-g g -l\t\tlist all volumes in group"));
1589*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1590*fcf3ce44SJohn Forte 		    gettext("\t-g -L\t\tlist all groups"));
1591*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1592*fcf3ce44SJohn Forte 		    gettext("\t-g g -m v v\tmove one or more volumes into "
1593*fcf3ce44SJohn Forte 		    "group"));
1594*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1595*fcf3ce44SJohn Forte 		    gettext("\t-g \"\" -m v\tremove volume from group"));
1596*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1597*fcf3ce44SJohn Forte 		    gettext("\t-g g -R\t\treset all volumes in group"));
1598*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1599*fcf3ce44SJohn Forte 		    gettext("\t-g g -A o\tattach overflow to all volumes in "
1600*fcf3ce44SJohn Forte 		    "group"));
1601*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1602*fcf3ce44SJohn Forte 		    gettext("\t-g g -D\t\tdetach overflow from all volumes in "
1603*fcf3ce44SJohn Forte 		    "group"));
1604*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1605*fcf3ce44SJohn Forte 		    gettext("\t-g g -E\t\texport shadow volume for all "
1606*fcf3ce44SJohn Forte 		    "volumes in group"));
1607*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1608*fcf3ce44SJohn Forte 		    gettext("\t-g g -P d u\tset copy delay/units for all "
1609*fcf3ce44SJohn Forte 		    "volumes in group"));
1610*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1611*fcf3ce44SJohn Forte 		    gettext("\t-g g -P\t\tget copy delay/units for all "
1612*fcf3ce44SJohn Forte 		    "volumes in group"));
1613*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1614*fcf3ce44SJohn Forte 		    gettext("\nLegend summary:"));
1615*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1616*fcf3ce44SJohn Forte 		    gettext("\tind\t\tindependent volume set"));
1617*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1618*fcf3ce44SJohn Forte 		    gettext("\tdep\t\tdependent volume set"));
1619*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1620*fcf3ce44SJohn Forte 		    gettext("\tall\t\tall configured volumes"));
1621*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1622*fcf3ce44SJohn Forte 		    gettext("\tm\t\tmaster volume"));
1623*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1624*fcf3ce44SJohn Forte 		    gettext("\ts\t\tshadow volume"));
1625*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1626*fcf3ce44SJohn Forte 		    gettext("\tv\t\tshadow volume (reference name)"));
1627*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1628*fcf3ce44SJohn Forte 		    gettext("\to\t\toverflow volume"));
1629*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1630*fcf3ce44SJohn Forte 		    gettext("\tb\t\tbitmap volume"));
1631*fcf3ce44SJohn Forte #ifdef DEBUG
1632*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1633*fcf3ce44SJohn Forte 		    gettext("\tf\t\tconfiguration file name"));
1634*fcf3ce44SJohn Forte #endif
1635*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1636*fcf3ce44SJohn Forte 		    gettext("\td\t\tdelay tick interval"));
1637*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1638*fcf3ce44SJohn Forte 		    gettext("\tu\t\tunit size"));
1639*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s\n",
1640*fcf3ce44SJohn Forte 		    gettext("\tg\t\tgroup name"));
1641*fcf3ce44SJohn Forte 
1642*fcf3ce44SJohn Forte 		/* assume we came here because user request help text */
1643*fcf3ce44SJohn Forte 		exit(0);
1644*fcf3ce44SJohn Forte 		/* NOTREACHED */
1645*fcf3ce44SJohn Forte 	}
1646*fcf3ce44SJohn Forte 
1647*fcf3ce44SJohn Forte }
1648*fcf3ce44SJohn Forte 
1649*fcf3ce44SJohn Forte static  char    yeschr[MAX_LINE_SIZE + 2];
1650*fcf3ce44SJohn Forte static  char    nochr[MAX_LINE_SIZE + 2];
1651*fcf3ce44SJohn Forte 
1652*fcf3ce44SJohn Forte static int
1653*fcf3ce44SJohn Forte yes(void)
1654*fcf3ce44SJohn Forte {
1655*fcf3ce44SJohn Forte 	int	i, b;
1656*fcf3ce44SJohn Forte 	char	ans[MAX_LINE_SIZE + 1];
1657*fcf3ce44SJohn Forte 
1658*fcf3ce44SJohn Forte 	for (i = 0; /*CSTYLED*/; i++) {
1659*fcf3ce44SJohn Forte 		b = getchar();
1660*fcf3ce44SJohn Forte 		if (b == '\n' || b == '\0' || b == EOF) {
1661*fcf3ce44SJohn Forte 			if (i < MAX_LINE_SIZE)
1662*fcf3ce44SJohn Forte 				ans[i] = 0;
1663*fcf3ce44SJohn Forte 			break;
1664*fcf3ce44SJohn Forte 		}
1665*fcf3ce44SJohn Forte 		if (i < MAX_LINE_SIZE)
1666*fcf3ce44SJohn Forte 			ans[i] = b;
1667*fcf3ce44SJohn Forte 	}
1668*fcf3ce44SJohn Forte 	if (i >= MAX_LINE_SIZE) {
1669*fcf3ce44SJohn Forte 		i = MAX_LINE_SIZE;
1670*fcf3ce44SJohn Forte 		ans[MAX_LINE_SIZE] = 0;
1671*fcf3ce44SJohn Forte 	}
1672*fcf3ce44SJohn Forte 	if ((i == 0) || (strncmp(yeschr, ans, i))) {
1673*fcf3ce44SJohn Forte 		if (strncmp(nochr, ans, i) == 0)
1674*fcf3ce44SJohn Forte 			return (0);
1675*fcf3ce44SJohn Forte 		else if (strncmp(yeschr, ans, i) == 0)
1676*fcf3ce44SJohn Forte 			return (1);
1677*fcf3ce44SJohn Forte 		else {
1678*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "%s %s/%s\n",
1679*fcf3ce44SJohn Forte 			    gettext("You have to respond with"),
1680*fcf3ce44SJohn Forte 			    yeschr, nochr);
1681*fcf3ce44SJohn Forte 			return (2);
1682*fcf3ce44SJohn Forte 		}
1683*fcf3ce44SJohn Forte 	}
1684*fcf3ce44SJohn Forte 	return (1);
1685*fcf3ce44SJohn Forte }
1686*fcf3ce44SJohn Forte 
1687*fcf3ce44SJohn Forte static int
1688*fcf3ce44SJohn Forte convert_int(char *str)
1689*fcf3ce44SJohn Forte {
1690*fcf3ce44SJohn Forte 	int result, rc;
1691*fcf3ce44SJohn Forte 	char *buf;
1692*fcf3ce44SJohn Forte 
1693*fcf3ce44SJohn Forte 	buf = (char *)calloc(strlen(str) + 256, sizeof (char));
1694*fcf3ce44SJohn Forte 	rc = sscanf(str, "%d%s", &result, buf);
1695*fcf3ce44SJohn Forte 
1696*fcf3ce44SJohn Forte 	if (rc != 1) {
1697*fcf3ce44SJohn Forte 		(void) sprintf(buf, gettext("'%s' is not a valid number"), str);
1698*fcf3ce44SJohn Forte 		/* dsw_error calls exit which frees 'buf' */
1699*fcf3ce44SJohn Forte 		errno = EINVAL;
1700*fcf3ce44SJohn Forte 		dsw_error(buf, NULL);
1701*fcf3ce44SJohn Forte 	}
1702*fcf3ce44SJohn Forte 	free(buf);
1703*fcf3ce44SJohn Forte 
1704*fcf3ce44SJohn Forte 	return (result);
1705*fcf3ce44SJohn Forte }
1706*fcf3ce44SJohn Forte 
1707*fcf3ce44SJohn Forte void
1708*fcf3ce44SJohn Forte check_action(char *will_happen)
1709*fcf3ce44SJohn Forte {
1710*fcf3ce44SJohn Forte 	int answer;
1711*fcf3ce44SJohn Forte 
1712*fcf3ce44SJohn Forte 	if (nflg || !isatty(fileno(stdin)))
1713*fcf3ce44SJohn Forte 		return;
1714*fcf3ce44SJohn Forte 	strncpy(yeschr, nl_langinfo(YESSTR), MAX_LINE_SIZE + 1);
1715*fcf3ce44SJohn Forte 	strncpy(nochr, nl_langinfo(NOSTR), MAX_LINE_SIZE + 1);
1716*fcf3ce44SJohn Forte 
1717*fcf3ce44SJohn Forte 	/*CONSTCOND*/
1718*fcf3ce44SJohn Forte 	while (1) {
1719*fcf3ce44SJohn Forte 		(void) printf("%s %s/%s ", will_happen, yeschr, nochr);
1720*fcf3ce44SJohn Forte 		answer = yes();
1721*fcf3ce44SJohn Forte 		if (answer == 1 || answer == 0)
1722*fcf3ce44SJohn Forte 			break;
1723*fcf3ce44SJohn Forte 	}
1724*fcf3ce44SJohn Forte 	if (answer == 1)
1725*fcf3ce44SJohn Forte 		return;
1726*fcf3ce44SJohn Forte 	exit(1);
1727*fcf3ce44SJohn Forte }
1728*fcf3ce44SJohn Forte 
1729*fcf3ce44SJohn Forte enum	child_event {Status, CopyStart};
1730*fcf3ce44SJohn Forte 
1731*fcf3ce44SJohn Forte /*
1732*fcf3ce44SJohn Forte  * Wait for child process to get to some state, where some state may be:
1733*fcf3ce44SJohn Forte  *
1734*fcf3ce44SJohn Forte  *	Status		Set up the shadow enough so that it responds
1735*fcf3ce44SJohn Forte  *			to status requests.
1736*fcf3ce44SJohn Forte  *	CopyStart	Start copy/update operations.
1737*fcf3ce44SJohn Forte  */
1738*fcf3ce44SJohn Forte 
1739*fcf3ce44SJohn Forte int
1740*fcf3ce44SJohn Forte child_wait(pid_t child, enum child_event event, char *volume)
1741*fcf3ce44SJohn Forte {
1742*fcf3ce44SJohn Forte 	dsw_stat_t	args;
1743*fcf3ce44SJohn Forte 	int rc;
1744*fcf3ce44SJohn Forte 
1745*fcf3ce44SJohn Forte 	strncpy(args.shadow_vol, volume, DSW_NAMELEN);
1746*fcf3ce44SJohn Forte 	args.shadow_vol[DSW_NAMELEN-1] = '\0';
1747*fcf3ce44SJohn Forte 
1748*fcf3ce44SJohn Forte 	for (; dead_child != child; sleep(1)) {
1749*fcf3ce44SJohn Forte 
1750*fcf3ce44SJohn Forte 		/* poll shadow group with a status ioctl() */
1751*fcf3ce44SJohn Forte 		args.status = spcs_s_ucreate();
1752*fcf3ce44SJohn Forte 		errno = 0;
1753*fcf3ce44SJohn Forte 		rc = do_ioctl(dsw_fd, DSWIOC_STAT, &args);
1754*fcf3ce44SJohn Forte 
1755*fcf3ce44SJohn Forte 		spcs_s_ufree(&args.status);
1756*fcf3ce44SJohn Forte 
1757*fcf3ce44SJohn Forte 		if (event == Status) {
1758*fcf3ce44SJohn Forte 			/* keep polling while we fail with DSW_ENOTFOUND */
1759*fcf3ce44SJohn Forte 			if (rc != -1 || errno != DSW_ENOTFOUND)
1760*fcf3ce44SJohn Forte 				return (0);
1761*fcf3ce44SJohn Forte 		} else {
1762*fcf3ce44SJohn Forte 			/* event == CopyStart */
1763*fcf3ce44SJohn Forte 			if (rc == -1) {
1764*fcf3ce44SJohn Forte 				return (1);	/* something wrong */
1765*fcf3ce44SJohn Forte 			}
1766*fcf3ce44SJohn Forte 			if (args.stat & DSW_COPYINGP)
1767*fcf3ce44SJohn Forte 				return (0);	/* copying underway */
1768*fcf3ce44SJohn Forte 		}
1769*fcf3ce44SJohn Forte 	}
1770*fcf3ce44SJohn Forte 	/* child died */
1771*fcf3ce44SJohn Forte 	if (WIFEXITED(dead_stat))
1772*fcf3ce44SJohn Forte 		return (WEXITSTATUS(dead_stat));
1773*fcf3ce44SJohn Forte 	else
1774*fcf3ce44SJohn Forte 		return (1);
1775*fcf3ce44SJohn Forte }
1776*fcf3ce44SJohn Forte 
1777*fcf3ce44SJohn Forte int
1778*fcf3ce44SJohn Forte mounted(char *t)
1779*fcf3ce44SJohn Forte {
1780*fcf3ce44SJohn Forte 	int	rdsk;
1781*fcf3ce44SJohn Forte 	int	i;
1782*fcf3ce44SJohn Forte 	FILE	*mntfp;
1783*fcf3ce44SJohn Forte 	struct mnttab mntref;
1784*fcf3ce44SJohn Forte 	struct mnttab mntent;
1785*fcf3ce44SJohn Forte 	char	target[DSW_NAMELEN];
1786*fcf3ce44SJohn Forte 	char	*s;
1787*fcf3ce44SJohn Forte 
1788*fcf3ce44SJohn Forte 	rdsk = i = 0;
1789*fcf3ce44SJohn Forte 	for (s = target; i < DSW_NAMELEN && (*s = *t++); i++) {
1790*fcf3ce44SJohn Forte 		if (*s == 'r' && rdsk == 0)
1791*fcf3ce44SJohn Forte 			rdsk = 1;
1792*fcf3ce44SJohn Forte 		else
1793*fcf3ce44SJohn Forte 			s++;
1794*fcf3ce44SJohn Forte 	}
1795*fcf3ce44SJohn Forte 	*s = '\0';
1796*fcf3ce44SJohn Forte 
1797*fcf3ce44SJohn Forte 	mntref.mnt_special = target;
1798*fcf3ce44SJohn Forte 	mntref.mnt_mountp = NULL;
1799*fcf3ce44SJohn Forte 	mntref.mnt_fstype = NULL;
1800*fcf3ce44SJohn Forte 	mntref.mnt_mntopts = NULL;
1801*fcf3ce44SJohn Forte 	mntref.mnt_time = NULL;
1802*fcf3ce44SJohn Forte 
1803*fcf3ce44SJohn Forte 	if ((mntfp = fopen("/etc/mnttab", "r")) == NULL) {
1804*fcf3ce44SJohn Forte 		dsw_error(gettext("Can not check volume against mount table"),
1805*fcf3ce44SJohn Forte 					NULL);
1806*fcf3ce44SJohn Forte 	}
1807*fcf3ce44SJohn Forte 	if (getmntany(mntfp, &mntent, &mntref) != -1) {
1808*fcf3ce44SJohn Forte 		/* found something before EOF */
1809*fcf3ce44SJohn Forte 		(void) fclose(mntfp);
1810*fcf3ce44SJohn Forte 		return (1);
1811*fcf3ce44SJohn Forte 	}
1812*fcf3ce44SJohn Forte 	(void) fclose(mntfp);
1813*fcf3ce44SJohn Forte 	return (0);
1814*fcf3ce44SJohn Forte }
1815*fcf3ce44SJohn Forte 
1816*fcf3ce44SJohn Forte void
1817*fcf3ce44SJohn Forte enable(char *master_volume, char *shadow_volume,
1818*fcf3ce44SJohn Forte 	char *bitmap_volume, char *copy_type)
1819*fcf3ce44SJohn Forte {
1820*fcf3ce44SJohn Forte 	dsw_config_t parms;
1821*fcf3ce44SJohn Forte 	dsw_ioctl_t temp;
1822*fcf3ce44SJohn Forte 	char	*p;
1823*fcf3ce44SJohn Forte 	int	rc;
1824*fcf3ce44SJohn Forte 	pid_t	child;
1825*fcf3ce44SJohn Forte 	spcs_s_info_t *sp_info;
1826*fcf3ce44SJohn Forte 	struct stat mstat, sstat, bstat;
1827*fcf3ce44SJohn Forte 	char	mst_dg[DSW_NAMELEN] = {0};
1828*fcf3ce44SJohn Forte 	char	shd_dg[DSW_NAMELEN] = {0};
1829*fcf3ce44SJohn Forte 	char	bmp_dg[DSW_NAMELEN] = {0};
1830*fcf3ce44SJohn Forte 	int	mvol_enabled;
1831*fcf3ce44SJohn Forte 	char	*altname;
1832*fcf3ce44SJohn Forte 	grptag_t *gdata;
1833*fcf3ce44SJohn Forte 
1834*fcf3ce44SJohn Forte 	bzero(&parms, sizeof (dsw_config_t));
1835*fcf3ce44SJohn Forte 
1836*fcf3ce44SJohn Forte 	if (strcmp(copy_type, "independent") == 0 ||
1837*fcf3ce44SJohn Forte 			strcmp(copy_type, gettext("independent")) == 0)
1838*fcf3ce44SJohn Forte 		parms.flag = DSW_GOLDEN;
1839*fcf3ce44SJohn Forte 	else if (strcmp(copy_type, "dependent") == 0 ||
1840*fcf3ce44SJohn Forte 			strcmp(copy_type, gettext("dependent")) == 0)
1841*fcf3ce44SJohn Forte 		parms.flag = 0;
1842*fcf3ce44SJohn Forte 	else
1843*fcf3ce44SJohn Forte 		dsw_error(gettext("don't understand shadow type"), NULL);
1844*fcf3ce44SJohn Forte 
1845*fcf3ce44SJohn Forte 	/* validate volume names */
1846*fcf3ce44SJohn Forte 	if (perform_autosv()) {
1847*fcf3ce44SJohn Forte 		if (cfg_load_svols(cfg) < 0 || cfg_load_dsvols(cfg) < 0 ||
1848*fcf3ce44SJohn Forte 		    cfg_load_shadows(cfg) < 0) {
1849*fcf3ce44SJohn Forte 			dsw_error(gettext("Unable to parse config file"), NULL);
1850*fcf3ce44SJohn Forte 		}
1851*fcf3ce44SJohn Forte 		load_ii_vols(cfg);
1852*fcf3ce44SJohn Forte 		reload_vols = LD_SVOLS | LD_DSVOLS | LD_SHADOWS | LD_II;
1853*fcf3ce44SJohn Forte 
1854*fcf3ce44SJohn Forte 		/* see if it's been used before under a different name */
1855*fcf3ce44SJohn Forte 		conform_name(&master_volume);
1856*fcf3ce44SJohn Forte 		conform_name(&shadow_volume);
1857*fcf3ce44SJohn Forte 		rc = cfg_get_canonical_name(cfg, bitmap_volume, &altname);
1858*fcf3ce44SJohn Forte 		if (rc < 0) {
1859*fcf3ce44SJohn Forte 			dsw_error(gettext("Unable to parse config file"), NULL);
1860*fcf3ce44SJohn Forte 		}
1861*fcf3ce44SJohn Forte 		if (rc) {
1862*fcf3ce44SJohn Forte 			errno = EBUSY;
1863*fcf3ce44SJohn Forte 			dsw_error(gettext("Bitmap in use"), NULL);
1864*fcf3ce44SJohn Forte 		}
1865*fcf3ce44SJohn Forte 	}
1866*fcf3ce44SJohn Forte 
1867*fcf3ce44SJohn Forte 	/*
1868*fcf3ce44SJohn Forte 	 * If not local, determine disk group names for volumes in II set
1869*fcf3ce44SJohn Forte 	 */
1870*fcf3ce44SJohn Forte 	switch (check_cluster()) {
1871*fcf3ce44SJohn Forte 	case II_CLUSTER:
1872*fcf3ce44SJohn Forte 		/*
1873*fcf3ce44SJohn Forte 		 * Check if none or all volumes are in a disk group
1874*fcf3ce44SJohn Forte 		 */
1875*fcf3ce44SJohn Forte 		rc = 0;
1876*fcf3ce44SJohn Forte 		if (check_diskgroup(master_volume, mst_dg)) rc++;
1877*fcf3ce44SJohn Forte 		if (check_diskgroup(shadow_volume, shd_dg)) rc++;
1878*fcf3ce44SJohn Forte 		if (check_diskgroup(bitmap_volume, bmp_dg)) rc++;
1879*fcf3ce44SJohn Forte 		if ((rc != 0) && (rc != 3))
1880*fcf3ce44SJohn Forte 			dsw_error(gettext(
1881*fcf3ce44SJohn Forte 				"Not all Point-in-Time Copy volumes are "
1882*fcf3ce44SJohn Forte 				"in a disk group"), NULL);
1883*fcf3ce44SJohn Forte 
1884*fcf3ce44SJohn Forte 		/*
1885*fcf3ce44SJohn Forte 		 * If volumes are not in a disk group, but are in a
1886*fcf3ce44SJohn Forte 		 * cluster, then "-C <tag>", must be set
1887*fcf3ce44SJohn Forte 		 */
1888*fcf3ce44SJohn Forte 		if (rc == 0 && cfg_cluster_tag == NULL)
1889*fcf3ce44SJohn Forte 			dsw_error(gettext(
1890*fcf3ce44SJohn Forte 				"Point-in-Time Copy volumes, that are not "
1891*fcf3ce44SJohn Forte 				"in a device group which has been "
1892*fcf3ce44SJohn Forte 				"registered with SunCluster, "
1893*fcf3ce44SJohn Forte 				"require usage of \"-C\""), NULL);
1894*fcf3ce44SJohn Forte 
1895*fcf3ce44SJohn Forte 		/*
1896*fcf3ce44SJohn Forte 		 * the same disk group
1897*fcf3ce44SJohn Forte 		 * If -n, plus mst_dg==bmp_dg, then allow E/I/J in SunCluster
1898*fcf3ce44SJohn Forte 		 */
1899*fcf3ce44SJohn Forte 		if ((strcmp(mst_dg, bmp_dg)) ||
1900*fcf3ce44SJohn Forte 		    (strcmp(mst_dg, shd_dg) && (!nflg)))
1901*fcf3ce44SJohn Forte 			    dsw_error(gettext(
1902*fcf3ce44SJohn Forte 				"Volumes are not in same disk group"), NULL);
1903*fcf3ce44SJohn Forte 
1904*fcf3ce44SJohn Forte 		/*
1905*fcf3ce44SJohn Forte 		 * Can never enable the same shadow twice, regardless of
1906*fcf3ce44SJohn Forte 		 * exportable shadow device group movement
1907*fcf3ce44SJohn Forte 		 */
1908*fcf3ce44SJohn Forte 		if (find_shadow_line(shadow_volume))
1909*fcf3ce44SJohn Forte 			dsw_error(gettext(
1910*fcf3ce44SJohn Forte 				"Shadow volume is already configured"), NULL);
1911*fcf3ce44SJohn Forte 
1912*fcf3ce44SJohn Forte 		/*
1913*fcf3ce44SJohn Forte 		 * Groups cannot span multiple clusters
1914*fcf3ce44SJohn Forte 		 */
1915*fcf3ce44SJohn Forte 		if (group_name && perform_autosv()) {
1916*fcf3ce44SJohn Forte 			gdata = (grptag_t *)nsc_lookup(volhash, group_name);
1917*fcf3ce44SJohn Forte 			if (gdata &&
1918*fcf3ce44SJohn Forte 			    strncmp(gdata->ctag, mst_dg, DSW_NAMELEN) != 0) {
1919*fcf3ce44SJohn Forte 				errno = EINVAL;
1920*fcf3ce44SJohn Forte 				dsw_error(gettext("Group contains sets not "
1921*fcf3ce44SJohn Forte 				    "in the same cluster resource"), NULL);
1922*fcf3ce44SJohn Forte 			}
1923*fcf3ce44SJohn Forte 		}
1924*fcf3ce44SJohn Forte 
1925*fcf3ce44SJohn Forte 		/*
1926*fcf3ce44SJohn Forte 		 * Check cluster tag and bitmap disk group
1927*fcf3ce44SJohn Forte 		 * set latter if different
1928*fcf3ce44SJohn Forte 		 */
1929*fcf3ce44SJohn Forte 		if (check_resource_group(bitmap_volume)) {
1930*fcf3ce44SJohn Forte 			/*
1931*fcf3ce44SJohn Forte 			 * Unload and reload in the event cluster tag has
1932*fcf3ce44SJohn Forte 			 * changed
1933*fcf3ce44SJohn Forte 			 */
1934*fcf3ce44SJohn Forte 			if (perform_autosv()) {
1935*fcf3ce44SJohn Forte 				unload_ii_vols();
1936*fcf3ce44SJohn Forte 				cfg_unload_shadows();
1937*fcf3ce44SJohn Forte 				cfg_unload_dsvols();
1938*fcf3ce44SJohn Forte 				cfg_unload_svols();
1939*fcf3ce44SJohn Forte 				if (cfg_load_svols(cfg) < 0 ||
1940*fcf3ce44SJohn Forte 				    cfg_load_dsvols(cfg) < 0 ||
1941*fcf3ce44SJohn Forte 				    cfg_load_shadows(cfg) < 0) {
1942*fcf3ce44SJohn Forte 					dsw_error(gettext(
1943*fcf3ce44SJohn Forte 					    "Unable to parse config "
1944*fcf3ce44SJohn Forte 					    "file"), NULL);
1945*fcf3ce44SJohn Forte 				}
1946*fcf3ce44SJohn Forte 				load_ii_vols(cfg);
1947*fcf3ce44SJohn Forte 			}
1948*fcf3ce44SJohn Forte 		}
1949*fcf3ce44SJohn Forte 		/*
1950*fcf3ce44SJohn Forte 		 * Copy cluster name into config
1951*fcf3ce44SJohn Forte 		 */
1952*fcf3ce44SJohn Forte 		strncpy(parms.cluster_tag, cfg_cluster_tag, DSW_NAMELEN);
1953*fcf3ce44SJohn Forte 		break;
1954*fcf3ce44SJohn Forte 
1955*fcf3ce44SJohn Forte 	case II_CLUSTER_LCL:
1956*fcf3ce44SJohn Forte 		/* ensure that the -C local won't interfere with the set */
1957*fcf3ce44SJohn Forte 		if (group_name && perform_autosv()) {
1958*fcf3ce44SJohn Forte 			gdata = (grptag_t *)nsc_lookup(volhash, group_name);
1959*fcf3ce44SJohn Forte 			if (gdata) {
1960*fcf3ce44SJohn Forte 				if (strlen(gdata->ctag) != 0) {
1961*fcf3ce44SJohn Forte 					errno = EINVAL;
1962*fcf3ce44SJohn Forte 					dsw_error(gettext("Unable to put set "
1963*fcf3ce44SJohn Forte 					    "into -C local and specified "
1964*fcf3ce44SJohn Forte 					    "group"), NULL);
1965*fcf3ce44SJohn Forte 				}
1966*fcf3ce44SJohn Forte 			}
1967*fcf3ce44SJohn Forte 		}
1968*fcf3ce44SJohn Forte 		break;
1969*fcf3ce44SJohn Forte 	}
1970*fcf3ce44SJohn Forte 
1971*fcf3ce44SJohn Forte 	/*
1972*fcf3ce44SJohn Forte 	 * If we've got a group name, add it into the config
1973*fcf3ce44SJohn Forte 	 */
1974*fcf3ce44SJohn Forte 	if (group_name) {
1975*fcf3ce44SJohn Forte 		strncpy(parms.group_name, group_name, DSW_NAMELEN);
1976*fcf3ce44SJohn Forte 	}
1977*fcf3ce44SJohn Forte 
1978*fcf3ce44SJohn Forte 	/*
1979*fcf3ce44SJohn Forte 	 * Determine accessability of volumes
1980*fcf3ce44SJohn Forte 	 */
1981*fcf3ce44SJohn Forte 	if (stat(master_volume, &mstat) != 0)
1982*fcf3ce44SJohn Forte 		dsw_error(gettext(
1983*fcf3ce44SJohn Forte 			"Unable to access master volume"), NULL);
1984*fcf3ce44SJohn Forte 	if (!S_ISCHR(mstat.st_mode))
1985*fcf3ce44SJohn Forte 		dsw_error(gettext(
1986*fcf3ce44SJohn Forte 			"Master volume is not a character device"), NULL);
1987*fcf3ce44SJohn Forte 	/* check the shadow_vol hasn't be used as SNDR secondary vol */
1988*fcf3ce44SJohn Forte 	check_iishadow(shadow_volume);
1989*fcf3ce44SJohn Forte 	if (stat(shadow_volume, &sstat) != 0)
1990*fcf3ce44SJohn Forte 		dsw_error(gettext(
1991*fcf3ce44SJohn Forte 			"Unable to access shadow volume"), NULL);
1992*fcf3ce44SJohn Forte 	if (!S_ISCHR(sstat.st_mode))
1993*fcf3ce44SJohn Forte 		dsw_error(gettext(
1994*fcf3ce44SJohn Forte 			"Shadow volume is not a character device"), NULL);
1995*fcf3ce44SJohn Forte 	if (mounted(shadow_volume)) {
1996*fcf3ce44SJohn Forte 		errno = EBUSY;
1997*fcf3ce44SJohn Forte 		dsw_error(gettext(
1998*fcf3ce44SJohn Forte 			"Shadow volume is mounted, unmount it first"), NULL);
1999*fcf3ce44SJohn Forte 	}
2000*fcf3ce44SJohn Forte 	if (mstat.st_rdev == sstat.st_rdev) {
2001*fcf3ce44SJohn Forte 		errno = EINVAL;
2002*fcf3ce44SJohn Forte 		dsw_error(gettext(
2003*fcf3ce44SJohn Forte 		    "Master and shadow are the same device"), NULL);
2004*fcf3ce44SJohn Forte 	}
2005*fcf3ce44SJohn Forte 	if (stat(bitmap_volume, &bstat) != 0) {
2006*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to access bitmap"), NULL);
2007*fcf3ce44SJohn Forte 	}
2008*fcf3ce44SJohn Forte 	if (!S_ISCHR(bstat.st_mode))
2009*fcf3ce44SJohn Forte 		dsw_error(gettext(
2010*fcf3ce44SJohn Forte 			"Bitmap volume is not a character device"), NULL);
2011*fcf3ce44SJohn Forte 	if (S_ISCHR(bstat.st_mode)) {
2012*fcf3ce44SJohn Forte 		if (mstat.st_rdev == bstat.st_rdev) {
2013*fcf3ce44SJohn Forte 			errno = EINVAL;
2014*fcf3ce44SJohn Forte 			dsw_error(gettext(
2015*fcf3ce44SJohn Forte 			    "Master and bitmap are the same device"), NULL);
2016*fcf3ce44SJohn Forte 		} else if (sstat.st_rdev == bstat.st_rdev) {
2017*fcf3ce44SJohn Forte 			errno = EINVAL;
2018*fcf3ce44SJohn Forte 			dsw_error(gettext(
2019*fcf3ce44SJohn Forte 			    "Shadow and bitmap are the same device"), NULL);
2020*fcf3ce44SJohn Forte 		}
2021*fcf3ce44SJohn Forte 	}
2022*fcf3ce44SJohn Forte 
2023*fcf3ce44SJohn Forte 	strncpy(parms.master_vol, master_volume, DSW_NAMELEN);
2024*fcf3ce44SJohn Forte 	strncpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
2025*fcf3ce44SJohn Forte 	strncpy(parms.bitmap_vol, bitmap_volume, DSW_NAMELEN);
2026*fcf3ce44SJohn Forte 	errno = 0;
2027*fcf3ce44SJohn Forte 	parms.status = spcs_s_ucreate();
2028*fcf3ce44SJohn Forte 
2029*fcf3ce44SJohn Forte 	/*
2030*fcf3ce44SJohn Forte 	 * Check that none of the member volumes forms part of another
2031*fcf3ce44SJohn Forte 	 * InstantImage group.
2032*fcf3ce44SJohn Forte 	 *
2033*fcf3ce44SJohn Forte 	 * -- this check has been removed; it is done in the kernel instead
2034*fcf3ce44SJohn Forte 	 * -- PJW
2035*fcf3ce44SJohn Forte 	 */
2036*fcf3ce44SJohn Forte 
2037*fcf3ce44SJohn Forte 	/*
2038*fcf3ce44SJohn Forte 	 * Check against overflow volumes
2039*fcf3ce44SJohn Forte 	 */
2040*fcf3ce44SJohn Forte 	for (p = get_overflow_list(); *p != NULL; p += DSW_NAMELEN) {
2041*fcf3ce44SJohn Forte 		if (strncmp(master_volume, p, DSW_NAMELEN) == 0)
2042*fcf3ce44SJohn Forte 			dsw_error(gettext(
2043*fcf3ce44SJohn Forte 				"Master volume is already an overflow volume"),
2044*fcf3ce44SJohn Forte 				NULL);
2045*fcf3ce44SJohn Forte 		else if (strncmp(shadow_volume, p, DSW_NAMELEN) == 0)
2046*fcf3ce44SJohn Forte 			dsw_error(gettext(
2047*fcf3ce44SJohn Forte 				"Shadow volume is already an overflow volume"),
2048*fcf3ce44SJohn Forte 				NULL);
2049*fcf3ce44SJohn Forte 		else if (strncmp(bitmap_volume, p, DSW_NAMELEN) == 0)
2050*fcf3ce44SJohn Forte 			dsw_error(gettext(
2051*fcf3ce44SJohn Forte 				"Bitmap volume is already an overflow volume"),
2052*fcf3ce44SJohn Forte 				NULL);
2053*fcf3ce44SJohn Forte 	}
2054*fcf3ce44SJohn Forte 
2055*fcf3ce44SJohn Forte 	/*
2056*fcf3ce44SJohn Forte 	 * Make sure that the shadow volume is not already configured
2057*fcf3ce44SJohn Forte 	 */
2058*fcf3ce44SJohn Forte 	if (find_shadow_config(shadow_volume, NULL, &temp))
2059*fcf3ce44SJohn Forte 		dsw_error(gettext(
2060*fcf3ce44SJohn Forte 			"Shadow volume is already configured"), NULL);
2061*fcf3ce44SJohn Forte 	if (perform_autosv()) {
2062*fcf3ce44SJohn Forte 		/*
2063*fcf3ce44SJohn Forte 		 * parse the dsvol entries to see if we need to place
2064*fcf3ce44SJohn Forte 		 * the master or shadow under SV control
2065*fcf3ce44SJohn Forte 		 */
2066*fcf3ce44SJohn Forte 		if (nsc_lookup(volhash, master_volume) == NULL) {
2067*fcf3ce44SJohn Forte 			if (cfg_vol_enable(cfg, master_volume, cfg_cluster_tag,
2068*fcf3ce44SJohn Forte 			    "ii") < 0) {
2069*fcf3ce44SJohn Forte 				dsw_error(
2070*fcf3ce44SJohn Forte 				    gettext("Cannot enable master volume"),
2071*fcf3ce44SJohn Forte 				    NULL);
2072*fcf3ce44SJohn Forte 			}
2073*fcf3ce44SJohn Forte 			mvol_enabled = 1;
2074*fcf3ce44SJohn Forte 		} else {
2075*fcf3ce44SJohn Forte 			mvol_enabled = 0;
2076*fcf3ce44SJohn Forte 		}
2077*fcf3ce44SJohn Forte 		if (nsc_lookup(volhash, shadow_volume) == NULL) {
2078*fcf3ce44SJohn Forte 			if (nflg) {
2079*fcf3ce44SJohn Forte 				cfg_resource(cfg, shd_dg);
2080*fcf3ce44SJohn Forte 				rc = cfg_vol_enable(cfg, shadow_volume,
2081*fcf3ce44SJohn Forte 					shd_dg, "ii");
2082*fcf3ce44SJohn Forte 				cfg_resource(cfg, cfg_cluster_tag);
2083*fcf3ce44SJohn Forte 			} else {
2084*fcf3ce44SJohn Forte 				rc = cfg_vol_enable(cfg, shadow_volume,
2085*fcf3ce44SJohn Forte 					cfg_cluster_tag, "ii");
2086*fcf3ce44SJohn Forte 			}
2087*fcf3ce44SJohn Forte 			if (rc < 0) {
2088*fcf3ce44SJohn Forte 				if (mvol_enabled) {
2089*fcf3ce44SJohn Forte 					if (cfg_vol_disable(cfg,
2090*fcf3ce44SJohn Forte 					    master_volume, cfg_cluster_tag,
2091*fcf3ce44SJohn Forte 					    "ii") < 0)
2092*fcf3ce44SJohn Forte 					    dsw_error(gettext(
2093*fcf3ce44SJohn Forte 						"SV disable of master failed"),
2094*fcf3ce44SJohn Forte 						NULL);
2095*fcf3ce44SJohn Forte 				}
2096*fcf3ce44SJohn Forte 				dsw_error(
2097*fcf3ce44SJohn Forte 				    gettext("Cannot enable shadow volume"),
2098*fcf3ce44SJohn Forte 				    NULL);
2099*fcf3ce44SJohn Forte 			}
2100*fcf3ce44SJohn Forte 		}
2101*fcf3ce44SJohn Forte 		unload_ii_vols();
2102*fcf3ce44SJohn Forte 		cfg_unload_shadows();
2103*fcf3ce44SJohn Forte 		cfg_unload_dsvols();
2104*fcf3ce44SJohn Forte 		cfg_unload_svols();
2105*fcf3ce44SJohn Forte 		reload_vols = 0;
2106*fcf3ce44SJohn Forte 	}
2107*fcf3ce44SJohn Forte 
2108*fcf3ce44SJohn Forte 	add_cfg_entry(&parms);
2109*fcf3ce44SJohn Forte 	cfg_unlock(cfg);
2110*fcf3ce44SJohn Forte 	config_locked = 0;
2111*fcf3ce44SJohn Forte 
2112*fcf3ce44SJohn Forte 	sigset(SIGCHLD, sigchild);
2113*fcf3ce44SJohn Forte 	switch (child = fork()) {
2114*fcf3ce44SJohn Forte 
2115*fcf3ce44SJohn Forte 	case (pid_t)-1:
2116*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to fork"), NULL);
2117*fcf3ce44SJohn Forte 		break;
2118*fcf3ce44SJohn Forte 
2119*fcf3ce44SJohn Forte 	case 0:
2120*fcf3ce44SJohn Forte 		rc = do_ioctl(dsw_fd, DSWIOC_ENABLE, &parms);
2121*fcf3ce44SJohn Forte 		if (rc == -1 && errno != DSW_EABORTED && errno != DSW_EIO) {
2122*fcf3ce44SJohn Forte 			/*
2123*fcf3ce44SJohn Forte 			 * Failed to enable shadow group, log problem and remove
2124*fcf3ce44SJohn Forte 			 * the shadow group from the config file.
2125*fcf3ce44SJohn Forte 			 */
2126*fcf3ce44SJohn Forte 			spcs_log("ii", &parms.status,
2127*fcf3ce44SJohn Forte 			    gettext("Enable failed %s %s %s (%s)"),
2128*fcf3ce44SJohn Forte 			    master_volume, shadow_volume, bitmap_volume,
2129*fcf3ce44SJohn Forte 			    parms.flag & DSW_GOLDEN ?
2130*fcf3ce44SJohn Forte 			    "independent" : "dependent");
2131*fcf3ce44SJohn Forte 
2132*fcf3ce44SJohn Forte 			if (!ii_lock(cfg, CFG_WRLOCK) ||
2133*fcf3ce44SJohn Forte 			    !find_shadow_config(shadow_volume, NULL, &temp)) {
2134*fcf3ce44SJohn Forte 				dsw_error(gettext(
2135*fcf3ce44SJohn Forte 					"Enable failed, can't tidy up cfg"),
2136*fcf3ce44SJohn Forte 					&parms.status);
2137*fcf3ce44SJohn Forte 			}
2138*fcf3ce44SJohn Forte 			config_locked = 1;
2139*fcf3ce44SJohn Forte 			remove_iiset(setnumber, shadow_volume, 0);
2140*fcf3ce44SJohn Forte 			dsw_error(gettext("Enable failed"), &parms.status);
2141*fcf3ce44SJohn Forte 		}
2142*fcf3ce44SJohn Forte 
2143*fcf3ce44SJohn Forte 		if (rc == -1)
2144*fcf3ce44SJohn Forte 			sp_info = &parms.status;
2145*fcf3ce44SJohn Forte 		else
2146*fcf3ce44SJohn Forte 			sp_info = NULL;
2147*fcf3ce44SJohn Forte 		spcs_log("ii", sp_info, gettext("Enabled %s %s %s (%s)"),
2148*fcf3ce44SJohn Forte 			master_volume, shadow_volume, bitmap_volume,
2149*fcf3ce44SJohn Forte 			parms.flag & DSW_GOLDEN ? "independent" : "dependent");
2150*fcf3ce44SJohn Forte 		spcs_s_ufree(&parms.status);
2151*fcf3ce44SJohn Forte 		break;
2152*fcf3ce44SJohn Forte 
2153*fcf3ce44SJohn Forte 	default:
2154*fcf3ce44SJohn Forte 		exit(child_wait(child, Status, shadow_volume));
2155*fcf3ce44SJohn Forte 		break;
2156*fcf3ce44SJohn Forte 	}
2157*fcf3ce44SJohn Forte }
2158*fcf3ce44SJohn Forte 
2159*fcf3ce44SJohn Forte int
2160*fcf3ce44SJohn Forte reset(char *volume)
2161*fcf3ce44SJohn Forte {
2162*fcf3ce44SJohn Forte 	dsw_ioctl_t args;
2163*fcf3ce44SJohn Forte 	dsw_config_t parms;
2164*fcf3ce44SJohn Forte 	int	rc;
2165*fcf3ce44SJohn Forte 	int	wait_loc;
2166*fcf3ce44SJohn Forte 	pid_t	child = (pid_t)0;
2167*fcf3ce44SJohn Forte 	enum copy_wait wait_action;
2168*fcf3ce44SJohn Forte 	spcs_s_info_t *stat;
2169*fcf3ce44SJohn Forte 	dsw_stat_t prev_stat;
2170*fcf3ce44SJohn Forte 	int stat_flags;
2171*fcf3ce44SJohn Forte 	static int unlocked = 0;
2172*fcf3ce44SJohn Forte 	int	do_enable = 0;
2173*fcf3ce44SJohn Forte 	char	key[CFG_MAX_KEY];
2174*fcf3ce44SJohn Forte 	char	optval[CFG_MAX_BUF];
2175*fcf3ce44SJohn Forte 	unsigned int flags;
2176*fcf3ce44SJohn Forte 
2177*fcf3ce44SJohn Forte 	wait_action = WaitForStart;
2178*fcf3ce44SJohn Forte 
2179*fcf3ce44SJohn Forte 	if (unlocked && !ii_lock(cfg, CFG_RDLOCK)) {
2180*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to set locking on the configuration"),
2181*fcf3ce44SJohn Forte 		    NULL);
2182*fcf3ce44SJohn Forte 	}
2183*fcf3ce44SJohn Forte 	config_locked = 1;
2184*fcf3ce44SJohn Forte 	if (!find_shadow_config(volume, &parms, &args))
2185*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
2186*fcf3ce44SJohn Forte 		    "group"), NULL);
2187*fcf3ce44SJohn Forte 
2188*fcf3ce44SJohn Forte 	cfg_unlock(cfg);
2189*fcf3ce44SJohn Forte 	config_locked = 0;
2190*fcf3ce44SJohn Forte 	unlocked = 1;
2191*fcf3ce44SJohn Forte 
2192*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("Start reset %s"), volume);
2193*fcf3ce44SJohn Forte 	strncpy(prev_stat.shadow_vol, volume, DSW_NAMELEN);
2194*fcf3ce44SJohn Forte 	prev_stat.shadow_vol[DSW_NAMELEN - 1] = '\0';
2195*fcf3ce44SJohn Forte 	prev_stat.status = spcs_s_ucreate();
2196*fcf3ce44SJohn Forte 	if (do_ioctl(dsw_fd, DSWIOC_STAT, &prev_stat) == -1) {
2197*fcf3ce44SJohn Forte 		/* set is suspended, so we do the enable processing instead */
2198*fcf3ce44SJohn Forte 		do_enable = 1;
2199*fcf3ce44SJohn Forte 
2200*fcf3ce44SJohn Forte 		/* first check to see whether the set was offline */
2201*fcf3ce44SJohn Forte 		snprintf(key, CFG_MAX_KEY, "ii.set%d.options", setnumber);
2202*fcf3ce44SJohn Forte 		if (!ii_lock(cfg, CFG_RDLOCK)) {
2203*fcf3ce44SJohn Forte 			dsw_error(gettext("Unable to set locking on the "
2204*fcf3ce44SJohn Forte 			    "configuration"), NULL);
2205*fcf3ce44SJohn Forte 		}
2206*fcf3ce44SJohn Forte 		config_locked = 1;
2207*fcf3ce44SJohn Forte 		unlocked = 0;
2208*fcf3ce44SJohn Forte 		if (cfg_get_single_option(cfg, CFG_SEC_CONF, key,
2209*fcf3ce44SJohn Forte 		    NSKERN_II_BMP_OPTION, optval, CFG_MAX_BUF) < 0) {
2210*fcf3ce44SJohn Forte 			dsw_error(gettext("unable to read config file"), NULL);
2211*fcf3ce44SJohn Forte 		}
2212*fcf3ce44SJohn Forte 		cfg_unlock(cfg);
2213*fcf3ce44SJohn Forte 		config_locked = 0;
2214*fcf3ce44SJohn Forte 		unlocked = 1;
2215*fcf3ce44SJohn Forte 		sscanf(optval, "%x", &flags);
2216*fcf3ce44SJohn Forte 		if ((flags & DSW_OFFLINE) == 0) {
2217*fcf3ce44SJohn Forte 			/* set wasn't offline - don't reset */
2218*fcf3ce44SJohn Forte 			dsw_error(gettext("Set not offline, will not reset"),
2219*fcf3ce44SJohn Forte 			    NULL);
2220*fcf3ce44SJohn Forte 		}
2221*fcf3ce44SJohn Forte 		parms.status = spcs_s_ucreate();
2222*fcf3ce44SJohn Forte 		stat = &parms.status;
2223*fcf3ce44SJohn Forte 		stat_flags = DSW_BMPOFFLINE;
2224*fcf3ce44SJohn Forte 	} else {
2225*fcf3ce44SJohn Forte 		args.status = spcs_s_ucreate();
2226*fcf3ce44SJohn Forte 		stat = &args.status;
2227*fcf3ce44SJohn Forte 		stat_flags = prev_stat.stat;
2228*fcf3ce44SJohn Forte 	}
2229*fcf3ce44SJohn Forte 	spcs_s_ufree(&prev_stat.status);
2230*fcf3ce44SJohn Forte 
2231*fcf3ce44SJohn Forte 	if (wait_action == WaitForStart)
2232*fcf3ce44SJohn Forte 		sigset(SIGCHLD, sigchild);
2233*fcf3ce44SJohn Forte 
2234*fcf3ce44SJohn Forte 	switch (child = fork()) {
2235*fcf3ce44SJohn Forte 
2236*fcf3ce44SJohn Forte 	case (pid_t)-1:
2237*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to fork"), NULL);
2238*fcf3ce44SJohn Forte 		break;
2239*fcf3ce44SJohn Forte 
2240*fcf3ce44SJohn Forte 	case 0:
2241*fcf3ce44SJohn Forte 		if (do_enable) {
2242*fcf3ce44SJohn Forte 			rc = do_ioctl(dsw_fd, DSWIOC_ENABLE, &parms);
2243*fcf3ce44SJohn Forte 		} else {
2244*fcf3ce44SJohn Forte 			rc = do_ioctl(dsw_fd, DSWIOC_RESET, &args);
2245*fcf3ce44SJohn Forte 		}
2246*fcf3ce44SJohn Forte 		if (rc == -1 && errno != DSW_EABORTED && errno != DSW_EIO) {
2247*fcf3ce44SJohn Forte 			spcs_log("ii", stat, gettext("Fail reset %s"), volume);
2248*fcf3ce44SJohn Forte 			dsw_error(gettext("Reset shadow failed"), stat);
2249*fcf3ce44SJohn Forte 		}
2250*fcf3ce44SJohn Forte 		/* last_overflow is set during find_shadow_config */
2251*fcf3ce44SJohn Forte 		if (strlen(last_overflow) > 0 &&
2252*fcf3ce44SJohn Forte 		    (stat_flags & (DSW_SHDOFFLINE | DSW_BMPOFFLINE)) != 0) {
2253*fcf3ce44SJohn Forte 			/* reattach it */
2254*fcf3ce44SJohn Forte 			strncpy(parms.bitmap_vol, last_overflow, DSW_NAMELEN);
2255*fcf3ce44SJohn Forte 			do_attach(&parms);
2256*fcf3ce44SJohn Forte 		}
2257*fcf3ce44SJohn Forte 		spcs_log("ii", stat, gettext("Finish reset %s"), volume);
2258*fcf3ce44SJohn Forte 		spcs_s_ufree(stat);
2259*fcf3ce44SJohn Forte 
2260*fcf3ce44SJohn Forte 		exit(0);
2261*fcf3ce44SJohn Forte 		break;
2262*fcf3ce44SJohn Forte 	default:
2263*fcf3ce44SJohn Forte 		if (wait_action == WaitForStart) {
2264*fcf3ce44SJohn Forte 			rc = child_wait(child, CopyStart, args.shadow_vol);
2265*fcf3ce44SJohn Forte 		} else { /* wait_action == WaitForEnd */
2266*fcf3ce44SJohn Forte 			wait_loc = 0;
2267*fcf3ce44SJohn Forte 			wait(&wait_loc);
2268*fcf3ce44SJohn Forte 			if (WIFEXITED(wait_loc) && (WEXITSTATUS(wait_loc) == 0))
2269*fcf3ce44SJohn Forte 				rc = 0;
2270*fcf3ce44SJohn Forte 			else
2271*fcf3ce44SJohn Forte 				rc = -1;
2272*fcf3ce44SJohn Forte 		}
2273*fcf3ce44SJohn Forte 		break;
2274*fcf3ce44SJohn Forte 	}
2275*fcf3ce44SJohn Forte 	/* if successful, remove flags entry from options field */
2276*fcf3ce44SJohn Forte 	if (rc >= 0) {
2277*fcf3ce44SJohn Forte 		if (!ii_lock(cfg, CFG_WRLOCK)) {
2278*fcf3ce44SJohn Forte 			dsw_error(gettext("Unable to set locking on the "
2279*fcf3ce44SJohn Forte 			    "configuration"), NULL);
2280*fcf3ce44SJohn Forte 		}
2281*fcf3ce44SJohn Forte 		config_locked = 1;
2282*fcf3ce44SJohn Forte 		if (!find_shadow_config(volume, &parms, &args)) {
2283*fcf3ce44SJohn Forte 			dsw_error(gettext("Volume is not in a Point-in-Time "
2284*fcf3ce44SJohn Forte 			    "Copy group"), NULL);
2285*fcf3ce44SJohn Forte 		}
2286*fcf3ce44SJohn Forte 		snprintf(key, CFG_MAX_KEY, "ii.set%d.options", setnumber);
2287*fcf3ce44SJohn Forte 		if (cfg_del_option(cfg, CFG_SEC_CONF, key, NSKERN_II_BMP_OPTION)
2288*fcf3ce44SJohn Forte 		    < 0) {
2289*fcf3ce44SJohn Forte 			dsw_error(gettext("Update of config failed"), NULL);
2290*fcf3ce44SJohn Forte 		}
2291*fcf3ce44SJohn Forte 		cfg_commit(cfg);
2292*fcf3ce44SJohn Forte 		cfg_unlock(cfg);
2293*fcf3ce44SJohn Forte 		config_locked = 0;
2294*fcf3ce44SJohn Forte 	}
2295*fcf3ce44SJohn Forte 
2296*fcf3ce44SJohn Forte 	return (rc);
2297*fcf3ce44SJohn Forte }
2298*fcf3ce44SJohn Forte 
2299*fcf3ce44SJohn Forte int
2300*fcf3ce44SJohn Forte overflow(char *volume)
2301*fcf3ce44SJohn Forte {
2302*fcf3ce44SJohn Forte 	dsw_ioctl_t args;
2303*fcf3ce44SJohn Forte 	int	rc;
2304*fcf3ce44SJohn Forte 	spcs_s_info_t *stat;
2305*fcf3ce44SJohn Forte 
2306*fcf3ce44SJohn Forte 	check_action(gettext("Initialize this overflow volume?"));
2307*fcf3ce44SJohn Forte 	if (find_matching_cf_line(volume, NULL, &args))
2308*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is part of a Point-in-Time Copy "
2309*fcf3ce44SJohn Forte 					    "group"), NULL);
2310*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
2311*fcf3ce44SJohn Forte 	strncpy(args.shadow_vol, volume, DSW_NAMELEN);
2312*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_OCREAT, &args);
2313*fcf3ce44SJohn Forte 	if (rc == -1) {
2314*fcf3ce44SJohn Forte 		spcs_log("ii", &args.status,
2315*fcf3ce44SJohn Forte 			gettext("Create overflow failed %s"), volume);
2316*fcf3ce44SJohn Forte 		dsw_error(gettext("Create overflow failed"), &args.status);
2317*fcf3ce44SJohn Forte 	}
2318*fcf3ce44SJohn Forte 	if (rc == -1)
2319*fcf3ce44SJohn Forte 		stat = &args.status;
2320*fcf3ce44SJohn Forte 	else
2321*fcf3ce44SJohn Forte 		stat = NULL;
2322*fcf3ce44SJohn Forte 	spcs_log("ii", stat, gettext("Create overflow succeeded %s"), volume);
2323*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
2324*fcf3ce44SJohn Forte 
2325*fcf3ce44SJohn Forte 	return (0);
2326*fcf3ce44SJohn Forte }
2327*fcf3ce44SJohn Forte 
2328*fcf3ce44SJohn Forte void
2329*fcf3ce44SJohn Forte bitmap_op(char *master_volume, int print_bitmap, int bitmap_percent, int used,
2330*fcf3ce44SJohn Forte     int is_compact)
2331*fcf3ce44SJohn Forte {
2332*fcf3ce44SJohn Forte 	unsigned char *bitmap;
2333*fcf3ce44SJohn Forte 	char *name;
2334*fcf3ce44SJohn Forte 	int i, x, y;
2335*fcf3ce44SJohn Forte 	unsigned j;
2336*fcf3ce44SJohn Forte 	unsigned long n;
2337*fcf3ce44SJohn Forte 	unsigned long percent;
2338*fcf3ce44SJohn Forte 
2339*fcf3ce44SJohn Forte 	bitmap = allocate_bitmap(master_volume);
2340*fcf3ce44SJohn Forte 	if (bitmap == NULL)
2341*fcf3ce44SJohn Forte 		return;
2342*fcf3ce44SJohn Forte 
2343*fcf3ce44SJohn Forte 	if (bitmap_percent) {
2344*fcf3ce44SJohn Forte 		/* count the number of bits set in bitmap */
2345*fcf3ce44SJohn Forte 		for (i = n = 0; i < bm_size; i++)
2346*fcf3ce44SJohn Forte 			for (j = (unsigned)bitmap[i]; j; j &= j -1)
2347*fcf3ce44SJohn Forte 				n++;
2348*fcf3ce44SJohn Forte 		if (is_compact)
2349*fcf3ce44SJohn Forte 			(void) printf(gettext("Chunks in map: %d used: %d\n"),
2350*fcf3ce44SJohn Forte 			    used, n);
2351*fcf3ce44SJohn Forte 		if (bm_actual < 100) {
2352*fcf3ce44SJohn Forte 			percent = 0;
2353*fcf3ce44SJohn Forte 		} else {
2354*fcf3ce44SJohn Forte 			percent = (n * 100) / bm_actual;
2355*fcf3ce44SJohn Forte 		}
2356*fcf3ce44SJohn Forte 		(void) printf(gettext("Percent of bitmap set: %u\n"), percent);
2357*fcf3ce44SJohn Forte 		percent = percent/100;
2358*fcf3ce44SJohn Forte 		/* distinguish between 0.0000% and 0.n% of bitmap set */
2359*fcf3ce44SJohn Forte 		if (percent < 1)
2360*fcf3ce44SJohn Forte 			(void) printf("\t(%s)\n", n > 0 ?
2361*fcf3ce44SJohn Forte 			    gettext("bitmap dirty") : gettext("bitmap clean"));
2362*fcf3ce44SJohn Forte 	}
2363*fcf3ce44SJohn Forte 
2364*fcf3ce44SJohn Forte 	if (print_bitmap) {
2365*fcf3ce44SJohn Forte 		name = strrchr(master_volume, '/');
2366*fcf3ce44SJohn Forte 		if (name++ == NULL)
2367*fcf3ce44SJohn Forte 		name = master_volume;
2368*fcf3ce44SJohn Forte 		i = bm_size * 8;
2369*fcf3ce44SJohn Forte 		x = (int)ceil(sqrt((double)i));
2370*fcf3ce44SJohn Forte 		x += (8 - (x % 8));	/* round up to nearest multiple of 8 */
2371*fcf3ce44SJohn Forte 		y = i / x;
2372*fcf3ce44SJohn Forte 		if (y * x < i)
2373*fcf3ce44SJohn Forte 			y++;
2374*fcf3ce44SJohn Forte 		(void) printf("#define bm%s_width %d\n#define bm%s_height %d\n",
2375*fcf3ce44SJohn Forte 		    name, x, name, y);
2376*fcf3ce44SJohn Forte 		(void) printf("#define bm%s_x_hot 0\n#define bm%s_y_hot 0\n",
2377*fcf3ce44SJohn Forte 		    name, name);
2378*fcf3ce44SJohn Forte 		(void) printf("static char bm%s_bits[] = {\n", name);
2379*fcf3ce44SJohn Forte 		for (i = 0; i < bm_size; i++) {
2380*fcf3ce44SJohn Forte 			if (i % 12 == 0)
2381*fcf3ce44SJohn Forte 				(void) printf("\n");
2382*fcf3ce44SJohn Forte 			(void) printf("0x%02x, ", bitmap[i]);
2383*fcf3ce44SJohn Forte 		}
2384*fcf3ce44SJohn Forte 		y = x * y;
2385*fcf3ce44SJohn Forte 		for (; i < y; i++) {
2386*fcf3ce44SJohn Forte 			if (i % 12 == 0)
2387*fcf3ce44SJohn Forte 				(void) printf("\n");
2388*fcf3ce44SJohn Forte 			(void) printf("0x00, ");
2389*fcf3ce44SJohn Forte 		}
2390*fcf3ce44SJohn Forte 		(void) printf("\n};\n");
2391*fcf3ce44SJohn Forte 	}
2392*fcf3ce44SJohn Forte 
2393*fcf3ce44SJohn Forte 	free_bitmap(bitmap);
2394*fcf3ce44SJohn Forte }
2395*fcf3ce44SJohn Forte 
2396*fcf3ce44SJohn Forte static int
2397*fcf3ce44SJohn Forte validate_group_names(char **vol_list, char *group)
2398*fcf3ce44SJohn Forte {
2399*fcf3ce44SJohn Forte 	ENTRY item, *found;
2400*fcf3ce44SJohn Forte 	int i, rc, count;
2401*fcf3ce44SJohn Forte 	dsw_aioctl_t *group_list;
2402*fcf3ce44SJohn Forte 	char *ptr;
2403*fcf3ce44SJohn Forte 
2404*fcf3ce44SJohn Forte 	if (group == NULL || *group == NULL) {
2405*fcf3ce44SJohn Forte 		/* no group set, just count volume list */
2406*fcf3ce44SJohn Forte 		for (i = 0; *vol_list++ != NULL; i++)
2407*fcf3ce44SJohn Forte 			;
2408*fcf3ce44SJohn Forte 		return (i);
2409*fcf3ce44SJohn Forte 	}
2410*fcf3ce44SJohn Forte 
2411*fcf3ce44SJohn Forte 	if ((count = do_ioctl(dsw_fd, DSWIOC_LISTLEN, NULL)) < 0)
2412*fcf3ce44SJohn Forte 		dsw_error("DSWIOC_LISTLEN", NULL);
2413*fcf3ce44SJohn Forte 
2414*fcf3ce44SJohn Forte 	group_list = malloc(sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
2415*fcf3ce44SJohn Forte 	if (group_list == NULL)
2416*fcf3ce44SJohn Forte 		dsw_error(gettext("Failed to allocate memory"), NULL);
2417*fcf3ce44SJohn Forte 
2418*fcf3ce44SJohn Forte 	bzero(group_list, sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
2419*fcf3ce44SJohn Forte 	group_list->count = count;
2420*fcf3ce44SJohn Forte 	group_list->flags = 0;
2421*fcf3ce44SJohn Forte 	group_list->status = spcs_s_ucreate();
2422*fcf3ce44SJohn Forte 	strncpy(group_list->shadow_vol, group, DSW_NAMELEN);
2423*fcf3ce44SJohn Forte 
2424*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_GLIST, group_list);
2425*fcf3ce44SJohn Forte 	if (rc < 0)
2426*fcf3ce44SJohn Forte 		dsw_error(gettext("Group list access failure"),
2427*fcf3ce44SJohn Forte 		    &group_list->status);
2428*fcf3ce44SJohn Forte 
2429*fcf3ce44SJohn Forte 	group_list->shadow_vol[DSW_NAMELEN * group_list->count] = '\0';
2430*fcf3ce44SJohn Forte 
2431*fcf3ce44SJohn Forte 	/* create hash and enter all volumes into it */
2432*fcf3ce44SJohn Forte 	if (hcreate(group_list->count) == 0)
2433*fcf3ce44SJohn Forte 		dsw_error(gettext("Failed to allocate memory"), NULL);
2434*fcf3ce44SJohn Forte 	ptr = group_list->shadow_vol;
2435*fcf3ce44SJohn Forte 	count = group_list->count;
2436*fcf3ce44SJohn Forte 	i = 0;
2437*fcf3ce44SJohn Forte 	while (i < count) {
2438*fcf3ce44SJohn Forte 		ptr[ DSW_NAMELEN - 1 ] = '\0';
2439*fcf3ce44SJohn Forte 		item.key = ptr;
2440*fcf3ce44SJohn Forte 		item.data = (void *) 0;
2441*fcf3ce44SJohn Forte 		(void) hsearch(item, ENTER);
2442*fcf3ce44SJohn Forte 		++i;
2443*fcf3ce44SJohn Forte 		ptr += DSW_NAMELEN;
2444*fcf3ce44SJohn Forte 	}
2445*fcf3ce44SJohn Forte 
2446*fcf3ce44SJohn Forte 	/* now compare the volume list with the hash */
2447*fcf3ce44SJohn Forte 	for (i = 0; vol_list[ i ]; i++) {
2448*fcf3ce44SJohn Forte 		item.key = vol_list[ i ];
2449*fcf3ce44SJohn Forte 		found = hsearch(item, FIND);
2450*fcf3ce44SJohn Forte 		if (!found)
2451*fcf3ce44SJohn Forte 			dsw_error(gettext("Group config does not match kernel"),
2452*fcf3ce44SJohn Forte 			    NULL);
2453*fcf3ce44SJohn Forte 		if (found->data != (void *) 0)
2454*fcf3ce44SJohn Forte 			dsw_error(gettext("Duplicate volume specified"), NULL);
2455*fcf3ce44SJohn Forte 		found->data = (void *) 1;
2456*fcf3ce44SJohn Forte 	}
2457*fcf3ce44SJohn Forte 	if (i != count)
2458*fcf3ce44SJohn Forte 		dsw_error(gettext("Group config does not match kernel"), NULL);
2459*fcf3ce44SJohn Forte 
2460*fcf3ce44SJohn Forte 	/* everything checks out */
2461*fcf3ce44SJohn Forte 	free(group_list);
2462*fcf3ce44SJohn Forte 	hdestroy();
2463*fcf3ce44SJohn Forte 
2464*fcf3ce44SJohn Forte 	return (count);
2465*fcf3ce44SJohn Forte }
2466*fcf3ce44SJohn Forte 
2467*fcf3ce44SJohn Forte int
2468*fcf3ce44SJohn Forte do_acopy(char **vol_list, enum copy_update update_mode,
2469*fcf3ce44SJohn Forte 		enum copy_direction direction)
2470*fcf3ce44SJohn Forte {
2471*fcf3ce44SJohn Forte 	dsw_aioctl_t *acopy_args;
2472*fcf3ce44SJohn Forte 	dsw_ioctl_t copy_args;
2473*fcf3ce44SJohn Forte 	dsw_config_t parms;
2474*fcf3ce44SJohn Forte 	dsw_stat_t	stat_s;
2475*fcf3ce44SJohn Forte 	int	i;
2476*fcf3ce44SJohn Forte 	int	rc;
2477*fcf3ce44SJohn Forte 	int	n_vols;
2478*fcf3ce44SJohn Forte 	char	*t;
2479*fcf3ce44SJohn Forte 	char	buf[1024];
2480*fcf3ce44SJohn Forte 	char	*sp;
2481*fcf3ce44SJohn Forte 	char	*ppid;
2482*fcf3ce44SJohn Forte 
2483*fcf3ce44SJohn Forte 	n_vols = validate_group_names(vol_list, group_name);
2484*fcf3ce44SJohn Forte 
2485*fcf3ce44SJohn Forte 	acopy_args = calloc(sizeof (dsw_aioctl_t) + n_vols * DSW_NAMELEN, 1);
2486*fcf3ce44SJohn Forte 	if (acopy_args == NULL)
2487*fcf3ce44SJohn Forte 		dsw_error(gettext("Too many volumes given for update"), NULL);
2488*fcf3ce44SJohn Forte 
2489*fcf3ce44SJohn Forte 	acopy_args->count = n_vols;
2490*fcf3ce44SJohn Forte 
2491*fcf3ce44SJohn Forte 	acopy_args->flags = 0;
2492*fcf3ce44SJohn Forte 
2493*fcf3ce44SJohn Forte 	if (update_mode == Update)
2494*fcf3ce44SJohn Forte 		acopy_args->flags |= CV_BMP_ONLY;
2495*fcf3ce44SJohn Forte 	if (direction == ToMaster)
2496*fcf3ce44SJohn Forte 		acopy_args->flags |= CV_SHD2MST;
2497*fcf3ce44SJohn Forte 	if (pflg) {
2498*fcf3ce44SJohn Forte 		acopy_args->flags |= CV_LOCK_PID;
2499*fcf3ce44SJohn Forte #ifdef DEBUG
2500*fcf3ce44SJohn Forte 		ppid = getenv("IIADM_PPID");
2501*fcf3ce44SJohn Forte 		if (ppid) {
2502*fcf3ce44SJohn Forte 			acopy_args->pid = atoi(ppid);
2503*fcf3ce44SJohn Forte 			fprintf(stderr, "(using %s for ppid)\n", ppid);
2504*fcf3ce44SJohn Forte 		} else {
2505*fcf3ce44SJohn Forte 			acopy_args->pid = getppid();
2506*fcf3ce44SJohn Forte 		}
2507*fcf3ce44SJohn Forte #else
2508*fcf3ce44SJohn Forte 		acopy_args->pid = getppid();
2509*fcf3ce44SJohn Forte #endif
2510*fcf3ce44SJohn Forte 	}
2511*fcf3ce44SJohn Forte 
2512*fcf3ce44SJohn Forte 	for (i = 0; i < n_vols; i++) {
2513*fcf3ce44SJohn Forte 		if (!find_shadow_config(vol_list[i], &parms, &copy_args))
2514*fcf3ce44SJohn Forte 			dsw_error(gettext("Volume is not in a Point-in-Time "
2515*fcf3ce44SJohn Forte 			    "group"), NULL);
2516*fcf3ce44SJohn Forte 		if (direction == ToMaster) {
2517*fcf3ce44SJohn Forte 			t = parms.master_vol;
2518*fcf3ce44SJohn Forte 		} else {
2519*fcf3ce44SJohn Forte 			t = parms.shadow_vol;
2520*fcf3ce44SJohn Forte 		}
2521*fcf3ce44SJohn Forte 
2522*fcf3ce44SJohn Forte 		if (mounted(t)) {
2523*fcf3ce44SJohn Forte 			errno = EBUSY;
2524*fcf3ce44SJohn Forte 			dsw_error(gettext("Target of copy/update is mounted, "
2525*fcf3ce44SJohn Forte 						"unmount it first"), NULL);
2526*fcf3ce44SJohn Forte 		}
2527*fcf3ce44SJohn Forte 
2528*fcf3ce44SJohn Forte 		strncpy(stat_s.shadow_vol, parms.shadow_vol, DSW_NAMELEN);
2529*fcf3ce44SJohn Forte 		stat_s.shadow_vol[DSW_NAMELEN-1] = '\0';
2530*fcf3ce44SJohn Forte 		stat_s.status = spcs_s_ucreate();
2531*fcf3ce44SJohn Forte 		rc = do_ioctl(dsw_fd, DSWIOC_STAT, &stat_s);
2532*fcf3ce44SJohn Forte 		spcs_s_ufree(&stat_s.status);
2533*fcf3ce44SJohn Forte 		if (rc == -1) {
2534*fcf3ce44SJohn Forte 			(void) sprintf(buf,
2535*fcf3ce44SJohn Forte 			    gettext("Shadow group %s is suspended"),
2536*fcf3ce44SJohn Forte 			    vol_list[i]);
2537*fcf3ce44SJohn Forte 			dsw_error(buf, NULL);
2538*fcf3ce44SJohn Forte 		}
2539*fcf3ce44SJohn Forte 
2540*fcf3ce44SJohn Forte 		if (stat_s.stat & DSW_COPYINGP) {
2541*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "%s: %s\n", cmdnam,
2542*fcf3ce44SJohn Forte 			    gettext("Copy already in progress"));
2543*fcf3ce44SJohn Forte 			exit(1);
2544*fcf3ce44SJohn Forte 		}
2545*fcf3ce44SJohn Forte 	}
2546*fcf3ce44SJohn Forte 	acopy_args->status = spcs_s_ucreate();
2547*fcf3ce44SJohn Forte 	for (i = 0; i < n_vols; i++) {
2548*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, gettext("Atomic %s %s %s"),
2549*fcf3ce44SJohn Forte 			update_mode == Update ?
2550*fcf3ce44SJohn Forte 				gettext("update") : gettext("copy"),
2551*fcf3ce44SJohn Forte 			vol_list[i],
2552*fcf3ce44SJohn Forte 			direction == ToMaster ?  gettext("from shadow") :
2553*fcf3ce44SJohn Forte 			gettext("to shadow"));
2554*fcf3ce44SJohn Forte 	}
2555*fcf3ce44SJohn Forte 	if (group_name == NULL || *group_name == NULL) {
2556*fcf3ce44SJohn Forte 		sp = acopy_args->shadow_vol;
2557*fcf3ce44SJohn Forte 		for (i = 0; i < n_vols; i++, sp += DSW_NAMELEN)
2558*fcf3ce44SJohn Forte 			strncpy(sp, vol_list[i], DSW_NAMELEN);
2559*fcf3ce44SJohn Forte 	} else {
2560*fcf3ce44SJohn Forte 		strncpy(acopy_args->shadow_vol, group_name, DSW_NAMELEN);
2561*fcf3ce44SJohn Forte 		acopy_args->flags |= CV_IS_GROUP;
2562*fcf3ce44SJohn Forte 	}
2563*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_ACOPY, acopy_args);
2564*fcf3ce44SJohn Forte 	if (rc == -1) {
2565*fcf3ce44SJohn Forte 		i = acopy_args->count;
2566*fcf3ce44SJohn Forte 		if (i < 0 || i >= n_vols) {
2567*fcf3ce44SJohn Forte 			spcs_log("ii", NULL, gettext("Atomic update failed"));
2568*fcf3ce44SJohn Forte 			(void) sprintf(buf, gettext("Update failed"));
2569*fcf3ce44SJohn Forte 		} else {
2570*fcf3ce44SJohn Forte 			spcs_log("ii", NULL,
2571*fcf3ce44SJohn Forte 				gettext("Atomic update of %s failed"),
2572*fcf3ce44SJohn Forte 				vol_list[acopy_args->count]);
2573*fcf3ce44SJohn Forte 			(void) sprintf(buf, gettext("Update of %s failed"),
2574*fcf3ce44SJohn Forte 			    vol_list[acopy_args->count]);
2575*fcf3ce44SJohn Forte 		}
2576*fcf3ce44SJohn Forte 		dsw_error(buf, &(acopy_args->status));
2577*fcf3ce44SJohn Forte 	}
2578*fcf3ce44SJohn Forte 	return (rc);
2579*fcf3ce44SJohn Forte }
2580*fcf3ce44SJohn Forte 
2581*fcf3ce44SJohn Forte int
2582*fcf3ce44SJohn Forte do_copy(char **vol_list, enum copy_update update_mode,
2583*fcf3ce44SJohn Forte 		enum copy_direction direction, enum copy_wait wait_action)
2584*fcf3ce44SJohn Forte {
2585*fcf3ce44SJohn Forte 	dsw_ioctl_t copy_args;
2586*fcf3ce44SJohn Forte 	dsw_config_t parms;
2587*fcf3ce44SJohn Forte 	dsw_stat_t	stat_s;
2588*fcf3ce44SJohn Forte 	int	rc;
2589*fcf3ce44SJohn Forte 	int	wait_loc;
2590*fcf3ce44SJohn Forte 	char	*t;
2591*fcf3ce44SJohn Forte 	char	*volume;
2592*fcf3ce44SJohn Forte 	pid_t	child = (pid_t)0;
2593*fcf3ce44SJohn Forte 	char	*ppid;
2594*fcf3ce44SJohn Forte 
2595*fcf3ce44SJohn Forte 	if (vol_list[0] && vol_list[1])
2596*fcf3ce44SJohn Forte 		return (do_acopy(vol_list, update_mode, direction));
2597*fcf3ce44SJohn Forte 
2598*fcf3ce44SJohn Forte 	volume = vol_list[0];
2599*fcf3ce44SJohn Forte 	if (!find_shadow_config(volume, &parms, &copy_args))
2600*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
2601*fcf3ce44SJohn Forte 					    "group"), NULL);
2602*fcf3ce44SJohn Forte 
2603*fcf3ce44SJohn Forte 	cfg_unlock(cfg);
2604*fcf3ce44SJohn Forte 	config_locked = 0;
2605*fcf3ce44SJohn Forte 	copy_args.flags = 0;
2606*fcf3ce44SJohn Forte 
2607*fcf3ce44SJohn Forte 	if (update_mode == Update)
2608*fcf3ce44SJohn Forte 		copy_args.flags |= CV_BMP_ONLY;
2609*fcf3ce44SJohn Forte 	if (direction == ToMaster) {
2610*fcf3ce44SJohn Forte 		copy_args.flags |= CV_SHD2MST;
2611*fcf3ce44SJohn Forte 		t = parms.master_vol;
2612*fcf3ce44SJohn Forte 	} else {
2613*fcf3ce44SJohn Forte 		t = parms.shadow_vol;
2614*fcf3ce44SJohn Forte 	}
2615*fcf3ce44SJohn Forte 	if (pflg) {
2616*fcf3ce44SJohn Forte 		copy_args.flags |= CV_LOCK_PID;
2617*fcf3ce44SJohn Forte #ifdef DEBUG
2618*fcf3ce44SJohn Forte 		ppid = getenv("IIADM_PPID");
2619*fcf3ce44SJohn Forte 		if (ppid) {
2620*fcf3ce44SJohn Forte 			copy_args.pid = atoi(ppid);
2621*fcf3ce44SJohn Forte 			fprintf(stderr, "(using %s for ppid)\n", ppid);
2622*fcf3ce44SJohn Forte 		} else {
2623*fcf3ce44SJohn Forte 			copy_args.pid = getppid();
2624*fcf3ce44SJohn Forte 		}
2625*fcf3ce44SJohn Forte #else
2626*fcf3ce44SJohn Forte 		copy_args.pid = getppid();
2627*fcf3ce44SJohn Forte #endif
2628*fcf3ce44SJohn Forte 	}
2629*fcf3ce44SJohn Forte 
2630*fcf3ce44SJohn Forte 	if (mounted(t)) {
2631*fcf3ce44SJohn Forte 		errno = EBUSY;
2632*fcf3ce44SJohn Forte 		dsw_error(gettext("Target of copy/update is mounted, "
2633*fcf3ce44SJohn Forte 					"unmount it first"), NULL);
2634*fcf3ce44SJohn Forte 	}
2635*fcf3ce44SJohn Forte 
2636*fcf3ce44SJohn Forte 	strncpy(stat_s.shadow_vol, copy_args.shadow_vol, DSW_NAMELEN);
2637*fcf3ce44SJohn Forte 	stat_s.shadow_vol[DSW_NAMELEN-1] = '\0';
2638*fcf3ce44SJohn Forte 	stat_s.status = spcs_s_ucreate();
2639*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_STAT, &stat_s);
2640*fcf3ce44SJohn Forte 	spcs_s_ufree(&stat_s.status);
2641*fcf3ce44SJohn Forte 	if (rc == -1)
2642*fcf3ce44SJohn Forte 		dsw_error(gettext("Shadow group suspended"), NULL);
2643*fcf3ce44SJohn Forte 
2644*fcf3ce44SJohn Forte 	if (stat_s.stat & DSW_COPYINGP) {
2645*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s: %s\n", cmdnam,
2646*fcf3ce44SJohn Forte 		    gettext("Copy already in progress"));
2647*fcf3ce44SJohn Forte 		exit(1);
2648*fcf3ce44SJohn Forte 	}
2649*fcf3ce44SJohn Forte 
2650*fcf3ce44SJohn Forte 	copy_args.status = spcs_s_ucreate();
2651*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("Start %s %s %s"),
2652*fcf3ce44SJohn Forte 			update_mode == Update ?
2653*fcf3ce44SJohn Forte 				gettext("update") : gettext("copy"),
2654*fcf3ce44SJohn Forte 			volume,
2655*fcf3ce44SJohn Forte 			direction == ToMaster ?  gettext("from shadow") :
2656*fcf3ce44SJohn Forte 			gettext("to shadow"));
2657*fcf3ce44SJohn Forte 
2658*fcf3ce44SJohn Forte 	if (wait_action == WaitForStart)
2659*fcf3ce44SJohn Forte 		sigset(SIGCHLD, sigchild);
2660*fcf3ce44SJohn Forte 	switch (child = fork()) {
2661*fcf3ce44SJohn Forte 
2662*fcf3ce44SJohn Forte 	case (pid_t)-1:
2663*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to fork"),
2664*fcf3ce44SJohn Forte 					NULL);
2665*fcf3ce44SJohn Forte 		break;
2666*fcf3ce44SJohn Forte 
2667*fcf3ce44SJohn Forte 	case 0:
2668*fcf3ce44SJohn Forte 		rc = do_ioctl(dsw_fd, DSWIOC_COPY, &copy_args);
2669*fcf3ce44SJohn Forte 		if (rc == -1) {
2670*fcf3ce44SJohn Forte 			spcs_log("ii", &copy_args.status,
2671*fcf3ce44SJohn Forte 			    gettext("Fail %s %s %s"),
2672*fcf3ce44SJohn Forte 			    update_mode == Update ?
2673*fcf3ce44SJohn Forte 					gettext("update") : gettext("copy"),
2674*fcf3ce44SJohn Forte 			    volume,
2675*fcf3ce44SJohn Forte 			    direction == ToMaster ?  gettext("from shadow")
2676*fcf3ce44SJohn Forte 					: gettext("to shadow"));
2677*fcf3ce44SJohn Forte 			dsw_error(gettext("Copy failed"), &copy_args.status);
2678*fcf3ce44SJohn Forte 		}
2679*fcf3ce44SJohn Forte 		spcs_s_ufree(&copy_args.status);
2680*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, gettext("Finish %s %s %s"),
2681*fcf3ce44SJohn Forte 		    update_mode == Update ?
2682*fcf3ce44SJohn Forte 				gettext("update") : gettext("copy"),
2683*fcf3ce44SJohn Forte 		    volume,
2684*fcf3ce44SJohn Forte 		    direction == ToMaster ?  gettext("from shadow") :
2685*fcf3ce44SJohn Forte 				gettext("to shadow"));
2686*fcf3ce44SJohn Forte 
2687*fcf3ce44SJohn Forte 		exit(0);
2688*fcf3ce44SJohn Forte 		break;
2689*fcf3ce44SJohn Forte 	default:
2690*fcf3ce44SJohn Forte 		if (wait_action == WaitForStart) {
2691*fcf3ce44SJohn Forte 			rc = child_wait(child, CopyStart, copy_args.shadow_vol);
2692*fcf3ce44SJohn Forte 		} else { /* wait_action == WaitForEnd */
2693*fcf3ce44SJohn Forte 			wait_loc = 0;
2694*fcf3ce44SJohn Forte 			wait(&wait_loc);
2695*fcf3ce44SJohn Forte 			if (WIFEXITED(wait_loc) && (WEXITSTATUS(wait_loc) == 0))
2696*fcf3ce44SJohn Forte 				rc = 0;
2697*fcf3ce44SJohn Forte 			else
2698*fcf3ce44SJohn Forte 				rc = 1;
2699*fcf3ce44SJohn Forte 		}
2700*fcf3ce44SJohn Forte 		break;
2701*fcf3ce44SJohn Forte 	}
2702*fcf3ce44SJohn Forte 	return (rc);
2703*fcf3ce44SJohn Forte }
2704*fcf3ce44SJohn Forte 
2705*fcf3ce44SJohn Forte void
2706*fcf3ce44SJohn Forte print_status(dsw_config_t *conf, int in_config)
2707*fcf3ce44SJohn Forte {
2708*fcf3ce44SJohn Forte 	dsw_stat_t args;
2709*fcf3ce44SJohn Forte 	int	stat_flags;
2710*fcf3ce44SJohn Forte 	static int need_sep = 0;
2711*fcf3ce44SJohn Forte 	time_t tmp_time;
2712*fcf3ce44SJohn Forte 
2713*fcf3ce44SJohn Forte 	if (need_sep++ > 0)
2714*fcf3ce44SJohn Forte 		(void) printf("--------------------------------------"
2715*fcf3ce44SJohn Forte 		    "----------------------------------------\n");
2716*fcf3ce44SJohn Forte 	strncpy(args.shadow_vol, conf->shadow_vol, DSW_NAMELEN);
2717*fcf3ce44SJohn Forte 	args.shadow_vol[DSW_NAMELEN-1] = '\0';
2718*fcf3ce44SJohn Forte 	if (in_config) {
2719*fcf3ce44SJohn Forte 		(void) printf("%s: %s\n",
2720*fcf3ce44SJohn Forte 		    conf->master_vol, gettext("(master volume)"));
2721*fcf3ce44SJohn Forte 		(void) printf("%s: %s\n",
2722*fcf3ce44SJohn Forte 		    conf->shadow_vol, gettext("(shadow volume)"));
2723*fcf3ce44SJohn Forte 		(void) printf("%s: %s\n",
2724*fcf3ce44SJohn Forte 		    conf->bitmap_vol, gettext("(bitmap volume)"));
2725*fcf3ce44SJohn Forte 	}
2726*fcf3ce44SJohn Forte 
2727*fcf3ce44SJohn Forte 	/*
2728*fcf3ce44SJohn Forte 	 * Do special checking on the status of this volume in a Sun Cluster
2729*fcf3ce44SJohn Forte 	 */
2730*fcf3ce44SJohn Forte 	if (check_cluster() == II_CLUSTER) {
2731*fcf3ce44SJohn Forte 	    char dgname[CFG_MAX_BUF], *other_node;
2732*fcf3ce44SJohn Forte 
2733*fcf3ce44SJohn Forte 	    if (cfg_dgname(conf->bitmap_vol, dgname, sizeof (dgname))) {
2734*fcf3ce44SJohn Forte 		if (strlen(dgname)) {
2735*fcf3ce44SJohn Forte 		    int rc = cfg_dgname_islocal(dgname, &other_node);
2736*fcf3ce44SJohn Forte 		    if (rc < 0) {
2737*fcf3ce44SJohn Forte 			(void) printf(gettext(
2738*fcf3ce44SJohn Forte 			    "Suspended on this node, not active elsewhere\n"));
2739*fcf3ce44SJohn Forte 			return;
2740*fcf3ce44SJohn Forte 		    } else if (rc == 0) {
2741*fcf3ce44SJohn Forte 			(void) printf(gettext(
2742*fcf3ce44SJohn Forte 				"Suspended on this node, active on %s\n"),
2743*fcf3ce44SJohn Forte 				other_node);
2744*fcf3ce44SJohn Forte 			return;
2745*fcf3ce44SJohn Forte 		    }
2746*fcf3ce44SJohn Forte 		}
2747*fcf3ce44SJohn Forte 	    }
2748*fcf3ce44SJohn Forte 	}
2749*fcf3ce44SJohn Forte 
2750*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
2751*fcf3ce44SJohn Forte 	if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1) {
2752*fcf3ce44SJohn Forte 
2753*fcf3ce44SJohn Forte 		/* Handle Not found or not in config */
2754*fcf3ce44SJohn Forte 		if (errno != DSW_ENOTFOUND || !in_config)
2755*fcf3ce44SJohn Forte 			dsw_error(gettext("Stat failed"), &args.status);
2756*fcf3ce44SJohn Forte 
2757*fcf3ce44SJohn Forte 		/* Just suspend */
2758*fcf3ce44SJohn Forte 		(void) printf(gettext("Suspended.\n"));
2759*fcf3ce44SJohn Forte 		return;
2760*fcf3ce44SJohn Forte 	}
2761*fcf3ce44SJohn Forte 
2762*fcf3ce44SJohn Forte 	if (args.overflow_vol[0] != '\0')
2763*fcf3ce44SJohn Forte 		(void) printf("%s: %s\n", args.overflow_vol,
2764*fcf3ce44SJohn Forte 		    gettext("(overflow volume)"));
2765*fcf3ce44SJohn Forte 
2766*fcf3ce44SJohn Forte 	if (conf->group_name[0] != '\0')
2767*fcf3ce44SJohn Forte 		(void) printf(gettext("Group name: %s\n"),
2768*fcf3ce44SJohn Forte 			    conf->group_name);
2769*fcf3ce44SJohn Forte 
2770*fcf3ce44SJohn Forte 	if (conf->cluster_tag[0] != '\0')
2771*fcf3ce44SJohn Forte 		(void) printf(gettext("Cluster tag: %s\n"),
2772*fcf3ce44SJohn Forte 			    conf->cluster_tag);
2773*fcf3ce44SJohn Forte 
2774*fcf3ce44SJohn Forte 	stat_flags = args.stat;
2775*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
2776*fcf3ce44SJohn Forte 	if (stat_flags & DSW_GOLDEN)
2777*fcf3ce44SJohn Forte 		(void) printf(gettext("Independent copy"));
2778*fcf3ce44SJohn Forte 	else
2779*fcf3ce44SJohn Forte 		(void) printf(gettext("Dependent copy"));
2780*fcf3ce44SJohn Forte 
2781*fcf3ce44SJohn Forte 	if (stat_flags & DSW_TREEMAP)
2782*fcf3ce44SJohn Forte 		(void) printf(gettext(", compacted shadow space"));
2783*fcf3ce44SJohn Forte 
2784*fcf3ce44SJohn Forte 	if (stat_flags & DSW_COPYINGP)
2785*fcf3ce44SJohn Forte 		(void) printf(gettext(", copy in progress"));
2786*fcf3ce44SJohn Forte 	else if (stat_flags & DSW_COPYING)
2787*fcf3ce44SJohn Forte 		(void) printf(gettext(", copy not active"));
2788*fcf3ce44SJohn Forte 
2789*fcf3ce44SJohn Forte 	if (stat_flags & DSW_COPYINGM)
2790*fcf3ce44SJohn Forte 		(void) printf(gettext(", copying master to shadow"));
2791*fcf3ce44SJohn Forte 
2792*fcf3ce44SJohn Forte 	if (stat_flags & DSW_COPYINGS)
2793*fcf3ce44SJohn Forte 		(void) printf(gettext(", copying shadow to master"));
2794*fcf3ce44SJohn Forte 
2795*fcf3ce44SJohn Forte 	if (stat_flags & DSW_COPYINGX)
2796*fcf3ce44SJohn Forte 		(void) printf(gettext(", abort of copy requested"));
2797*fcf3ce44SJohn Forte 
2798*fcf3ce44SJohn Forte 	if (stat_flags & DSW_MSTOFFLINE)
2799*fcf3ce44SJohn Forte 		(void) printf(gettext(", master volume offline"));
2800*fcf3ce44SJohn Forte 
2801*fcf3ce44SJohn Forte 	if (stat_flags & DSW_SHDOFFLINE)
2802*fcf3ce44SJohn Forte 		(void) printf(gettext(", shadow volume offline"));
2803*fcf3ce44SJohn Forte 
2804*fcf3ce44SJohn Forte 	if (stat_flags & DSW_BMPOFFLINE)
2805*fcf3ce44SJohn Forte 		(void) printf(gettext(", bitmap volume offline"));
2806*fcf3ce44SJohn Forte 
2807*fcf3ce44SJohn Forte 	if (stat_flags & DSW_OVROFFLINE)
2808*fcf3ce44SJohn Forte 		(void) printf(gettext(", overflow volume offline"));
2809*fcf3ce44SJohn Forte 
2810*fcf3ce44SJohn Forte 	if (stat_flags & DSW_SHDEXPORT)
2811*fcf3ce44SJohn Forte 		(void) printf(gettext(", shadow volume exported"));
2812*fcf3ce44SJohn Forte 
2813*fcf3ce44SJohn Forte 	if (stat_flags & DSW_SHDIMPORT)
2814*fcf3ce44SJohn Forte 		(void) printf(gettext(", shadow volume imported"));
2815*fcf3ce44SJohn Forte 
2816*fcf3ce44SJohn Forte 	if (stat_flags & DSW_OVERFLOW)
2817*fcf3ce44SJohn Forte 		(void) printf(gettext(", out of space"));
2818*fcf3ce44SJohn Forte 
2819*fcf3ce44SJohn Forte 	if (stat_flags & DSW_VOVERFLOW)
2820*fcf3ce44SJohn Forte 		(void) printf(gettext(", spilled into overflow volume"));
2821*fcf3ce44SJohn Forte 	(void) printf("\n");
2822*fcf3ce44SJohn Forte 
2823*fcf3ce44SJohn Forte 	tmp_time = args.mtime;
2824*fcf3ce44SJohn Forte 	if (tmp_time != 0)
2825*fcf3ce44SJohn Forte 		(void) printf("%s %s", gettext("Latest modified time:"),
2826*fcf3ce44SJohn Forte 			ctime(&tmp_time));
2827*fcf3ce44SJohn Forte 	else
2828*fcf3ce44SJohn Forte 		(void) printf("%s\n", gettext("Latest modified time: unknown"));
2829*fcf3ce44SJohn Forte 
2830*fcf3ce44SJohn Forte 	(void) printf("%s %8llu\n", gettext("Volume size:"), args.size);
2831*fcf3ce44SJohn Forte 	if (args.shdsize != 0) {
2832*fcf3ce44SJohn Forte 		(void) printf("%s %lld %s %lld\n",
2833*fcf3ce44SJohn Forte 			gettext("Shadow chunks total:"), args.shdsize,
2834*fcf3ce44SJohn Forte 			gettext("Shadow chunks used:"), args.shdused);
2835*fcf3ce44SJohn Forte 	}
2836*fcf3ce44SJohn Forte 	bitmap_op(args.shadow_vol, 0, 1, 0, 0);
2837*fcf3ce44SJohn Forte }
2838*fcf3ce44SJohn Forte 
2839*fcf3ce44SJohn Forte int
2840*fcf3ce44SJohn Forte abort_copy(char *volume)
2841*fcf3ce44SJohn Forte {
2842*fcf3ce44SJohn Forte 	dsw_ioctl_t args;
2843*fcf3ce44SJohn Forte 
2844*fcf3ce44SJohn Forte 	if (!find_shadow_config(volume, NULL, &args))
2845*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
2846*fcf3ce44SJohn Forte 						"group"), NULL);
2847*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
2848*fcf3ce44SJohn Forte 	if (do_ioctl(dsw_fd, DSWIOC_ABORT, &args)  == -1)
2849*fcf3ce44SJohn Forte 		dsw_error(gettext("Abort failed"), &args.status);
2850*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("Abort %s"), args.shadow_vol);
2851*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
2852*fcf3ce44SJohn Forte 	return (0);
2853*fcf3ce44SJohn Forte }
2854*fcf3ce44SJohn Forte 
2855*fcf3ce44SJohn Forte void
2856*fcf3ce44SJohn Forte iiversion()
2857*fcf3ce44SJohn Forte {
2858*fcf3ce44SJohn Forte 	dsw_version_t args;
2859*fcf3ce44SJohn Forte 
2860*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
2861*fcf3ce44SJohn Forte 	if (do_ioctl(dsw_fd, DSWIOC_VERSION, &args)  == -1)
2862*fcf3ce44SJohn Forte 		dsw_error(gettext("Version failed"), &args.status);
2863*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
2864*fcf3ce44SJohn Forte #ifdef DEBUG
2865*fcf3ce44SJohn Forte 	(void) printf(gettext("Point in Time Copy version %d.%d.%d.%d\n"),
2866*fcf3ce44SJohn Forte 	    args.major, args.minor, args.micro, args.baseline);
2867*fcf3ce44SJohn Forte #else
2868*fcf3ce44SJohn Forte 	if (args.micro) {
2869*fcf3ce44SJohn Forte 		(void) printf(gettext("Point in Time Copy version %d.%d.%d\n"),
2870*fcf3ce44SJohn Forte 		    args.major, args.minor, args.micro);
2871*fcf3ce44SJohn Forte 	} else {
2872*fcf3ce44SJohn Forte 		(void) printf(gettext("Point in Time Copy version %d.%d\n"),
2873*fcf3ce44SJohn Forte 		    args.major, args.minor);
2874*fcf3ce44SJohn Forte 	}
2875*fcf3ce44SJohn Forte #endif
2876*fcf3ce44SJohn Forte }
2877*fcf3ce44SJohn Forte 
2878*fcf3ce44SJohn Forte void
2879*fcf3ce44SJohn Forte list_volumes()
2880*fcf3ce44SJohn Forte {
2881*fcf3ce44SJohn Forte 	dsw_list_t args;
2882*fcf3ce44SJohn Forte 	int i, set, found;
2883*fcf3ce44SJohn Forte 	dsw_config_t *lp;
2884*fcf3ce44SJohn Forte 	ENTRY item, *ip;
2885*fcf3ce44SJohn Forte 	dsw_config_t parms;
2886*fcf3ce44SJohn Forte 
2887*fcf3ce44SJohn Forte 	if ((i = do_ioctl(dsw_fd, DSWIOC_LISTLEN, &args)) == -1)
2888*fcf3ce44SJohn Forte 		dsw_error("DSWIOC_LISTLEN", NULL);
2889*fcf3ce44SJohn Forte 
2890*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
2891*fcf3ce44SJohn Forte 	args.list_used = 0;
2892*fcf3ce44SJohn Forte 	args.list_size = i + 4;
2893*fcf3ce44SJohn Forte 	lp = args.list = (dsw_config_t *)
2894*fcf3ce44SJohn Forte 	    malloc(args.list_size * sizeof (dsw_config_t));
2895*fcf3ce44SJohn Forte 
2896*fcf3ce44SJohn Forte 	if (args.list == NULL)
2897*fcf3ce44SJohn Forte 		dsw_error(gettext("Failed to allocate memory"), NULL);
2898*fcf3ce44SJohn Forte 	if (do_ioctl(dsw_fd, DSWIOC_LIST, &args)  == -1)
2899*fcf3ce44SJohn Forte 		dsw_error(gettext("List failed"), &args.status);
2900*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
2901*fcf3ce44SJohn Forte 
2902*fcf3ce44SJohn Forte 	/* make a hashtable */
2903*fcf3ce44SJohn Forte 	if (args.list_used > 0) {
2904*fcf3ce44SJohn Forte 		if (hcreate(args.list_used) == 0) {
2905*fcf3ce44SJohn Forte 			dsw_error(gettext("Failed to allocate memory"), NULL);
2906*fcf3ce44SJohn Forte 			/*NOTREACHED*/
2907*fcf3ce44SJohn Forte 		}
2908*fcf3ce44SJohn Forte 	}
2909*fcf3ce44SJohn Forte 
2910*fcf3ce44SJohn Forte 	/* populate the hashtable */
2911*fcf3ce44SJohn Forte 	for (i = 0; i < args.list_used; i++, lp++) {
2912*fcf3ce44SJohn Forte 		item.key = lp->shadow_vol;
2913*fcf3ce44SJohn Forte 		item.data = (char *)lp;
2914*fcf3ce44SJohn Forte 		if (hsearch(item, ENTER) == NULL) {
2915*fcf3ce44SJohn Forte 			dsw_error(gettext("Failed to allocate memory"), NULL);
2916*fcf3ce44SJohn Forte 			/*NOTREACHED*/
2917*fcf3ce44SJohn Forte 		}
2918*fcf3ce44SJohn Forte 	}
2919*fcf3ce44SJohn Forte 
2920*fcf3ce44SJohn Forte 	/* perform action for each line of the stored config file */
2921*fcf3ce44SJohn Forte 	for (set = 1; get_dsw_config(set, &parms) == 0; set++) {
2922*fcf3ce44SJohn Forte 
2923*fcf3ce44SJohn Forte 		/* Are there any II sets configured on this node? */
2924*fcf3ce44SJohn Forte 		if (args.list_used > 0) {
2925*fcf3ce44SJohn Forte 			item.key = parms.shadow_vol;
2926*fcf3ce44SJohn Forte 
2927*fcf3ce44SJohn Forte 			/* Is this volume configured on this node? */
2928*fcf3ce44SJohn Forte 			if (ip = hsearch(item, FIND)) {
2929*fcf3ce44SJohn Forte 
2930*fcf3ce44SJohn Forte 				/* Handle Imported Shadows */
2931*fcf3ce44SJohn Forte 				/* LINTED alignment of cast ok */
2932*fcf3ce44SJohn Forte 				lp = (dsw_config_t *)ip->data;
2933*fcf3ce44SJohn Forte 				if (strcmp(parms.master_vol,
2934*fcf3ce44SJohn Forte 					II_IMPORTED_SHADOW))
2935*fcf3ce44SJohn Forte 					found = !(lp->flag & DSW_SHDIMPORT);
2936*fcf3ce44SJohn Forte 				else
2937*fcf3ce44SJohn Forte 					found = (lp->flag & DSW_SHDIMPORT);
2938*fcf3ce44SJohn Forte 			}
2939*fcf3ce44SJohn Forte 			else
2940*fcf3ce44SJohn Forte 				found = FALSE;
2941*fcf3ce44SJohn Forte 		}
2942*fcf3ce44SJohn Forte 		else
2943*fcf3ce44SJohn Forte 			found = FALSE;
2944*fcf3ce44SJohn Forte 
2945*fcf3ce44SJohn Forte 		if ((cfg_cluster_tag) &&
2946*fcf3ce44SJohn Forte 			strcmp(cfg_cluster_tag, parms.cluster_tag))
2947*fcf3ce44SJohn Forte 			continue;
2948*fcf3ce44SJohn Forte 
2949*fcf3ce44SJohn Forte 		if ((group_name) && strcmp(group_name, parms.group_name))
2950*fcf3ce44SJohn Forte 			continue;
2951*fcf3ce44SJohn Forte 
2952*fcf3ce44SJohn Forte 		(void) printf("%s %.*s %.*s %.*s%s\n",
2953*fcf3ce44SJohn Forte 		    (parms.flag & DSW_GOLDEN) ? "ind" : "dep",
2954*fcf3ce44SJohn Forte 		    DSW_NAMELEN, parms.master_vol,
2955*fcf3ce44SJohn Forte 		    DSW_NAMELEN, parms.shadow_vol,
2956*fcf3ce44SJohn Forte 		    DSW_NAMELEN, parms.bitmap_vol,
2957*fcf3ce44SJohn Forte 		    found ? "" : gettext(" (suspended)"));
2958*fcf3ce44SJohn Forte 	}
2959*fcf3ce44SJohn Forte 	hdestroy();
2960*fcf3ce44SJohn Forte 	free(args.list);
2961*fcf3ce44SJohn Forte }
2962*fcf3ce44SJohn Forte 
2963*fcf3ce44SJohn Forte int
2964*fcf3ce44SJohn Forte wait_for_copy(char *volume)
2965*fcf3ce44SJohn Forte {
2966*fcf3ce44SJohn Forte 	dsw_ioctl_t parms;
2967*fcf3ce44SJohn Forte 	int rc;
2968*fcf3ce44SJohn Forte 	static int unlocked = 0;
2969*fcf3ce44SJohn Forte 	char *ppid;
2970*fcf3ce44SJohn Forte 
2971*fcf3ce44SJohn Forte 	if (unlocked && !ii_lock(cfg, CFG_RDLOCK)) {
2972*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to set locking on the configuration"),
2973*fcf3ce44SJohn Forte 		    NULL);
2974*fcf3ce44SJohn Forte 	}
2975*fcf3ce44SJohn Forte 	config_locked = 1;
2976*fcf3ce44SJohn Forte 	if (!find_shadow_config(volume, NULL, &parms))
2977*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
2978*fcf3ce44SJohn Forte 						"group"), NULL);
2979*fcf3ce44SJohn Forte 	cfg_unlock(cfg);
2980*fcf3ce44SJohn Forte 	config_locked = 0;
2981*fcf3ce44SJohn Forte 	unlocked = 1;
2982*fcf3ce44SJohn Forte 
2983*fcf3ce44SJohn Forte 	parms.status = spcs_s_ucreate();
2984*fcf3ce44SJohn Forte 	if (pflg) {
2985*fcf3ce44SJohn Forte #ifdef DEBUG
2986*fcf3ce44SJohn Forte 		ppid = getenv("IIADM_PPID");
2987*fcf3ce44SJohn Forte 		if (ppid) {
2988*fcf3ce44SJohn Forte 			parms.pid = atoi(ppid);
2989*fcf3ce44SJohn Forte 			fprintf(stderr, "(using %s for ppid)\n", ppid);
2990*fcf3ce44SJohn Forte 		} else {
2991*fcf3ce44SJohn Forte 			parms.pid = (nflg) ? -1 : getppid();
2992*fcf3ce44SJohn Forte 		}
2993*fcf3ce44SJohn Forte #else
2994*fcf3ce44SJohn Forte 		parms.pid = (nflg) ? -1 : getppid();
2995*fcf3ce44SJohn Forte #endif
2996*fcf3ce44SJohn Forte 		parms.flags |= CV_LOCK_PID;
2997*fcf3ce44SJohn Forte 	}
2998*fcf3ce44SJohn Forte 
2999*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_WAIT, &parms);
3000*fcf3ce44SJohn Forte 	if (rc == -1)
3001*fcf3ce44SJohn Forte 		dsw_error(gettext("Wait failed"), &parms.status);
3002*fcf3ce44SJohn Forte 	spcs_s_ufree(&parms.status);
3003*fcf3ce44SJohn Forte 	return (0);
3004*fcf3ce44SJohn Forte }
3005*fcf3ce44SJohn Forte 
3006*fcf3ce44SJohn Forte int
3007*fcf3ce44SJohn Forte export(char *volume)
3008*fcf3ce44SJohn Forte {
3009*fcf3ce44SJohn Forte 	dsw_ioctl_t parms;
3010*fcf3ce44SJohn Forte 	dsw_config_t conf;
3011*fcf3ce44SJohn Forte 	char *old_ctag, dgname[DSW_NAMELEN];
3012*fcf3ce44SJohn Forte 	int rc;
3013*fcf3ce44SJohn Forte 
3014*fcf3ce44SJohn Forte 	if (!find_shadow_config(volume, &conf, &parms))
3015*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
3016*fcf3ce44SJohn Forte 				"group"), NULL);
3017*fcf3ce44SJohn Forte 	if (mounted(volume))
3018*fcf3ce44SJohn Forte 		dsw_error(gettext("Can't export a mounted volume"), NULL);
3019*fcf3ce44SJohn Forte 
3020*fcf3ce44SJohn Forte 	/* If this is an exportable shadow in the cluster, change ctag */
3021*fcf3ce44SJohn Forte 	if (strlen(conf.cluster_tag) &&
3022*fcf3ce44SJohn Forte 	    (cfg_dgname(volume, dgname, sizeof (dgname)))) {
3023*fcf3ce44SJohn Forte 		old_ctag = cfg_cluster_tag;
3024*fcf3ce44SJohn Forte 		cfg_resource(cfg, cfg_cluster_tag = strdup(dgname));
3025*fcf3ce44SJohn Forte 	} else	old_ctag = NULL;
3026*fcf3ce44SJohn Forte 
3027*fcf3ce44SJohn Forte 	if (cfg_load_dsvols(cfg) < 0 || cfg_load_shadows(cfg) < 0) {
3028*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to parse config file"), NULL);
3029*fcf3ce44SJohn Forte 	}
3030*fcf3ce44SJohn Forte 	reload_vols = LD_DSVOLS | LD_SHADOWS;
3031*fcf3ce44SJohn Forte 	conform_name(&volume);
3032*fcf3ce44SJohn Forte 
3033*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("Export %s"), volume);
3034*fcf3ce44SJohn Forte 	parms.status = spcs_s_ucreate();
3035*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_EXPORT, &parms);
3036*fcf3ce44SJohn Forte 	if (rc == -1)
3037*fcf3ce44SJohn Forte 		dsw_error(gettext("Export failed"), &parms.status);
3038*fcf3ce44SJohn Forte 	if (perform_autosv()) {
3039*fcf3ce44SJohn Forte 		if (cfg_vol_disable(cfg, volume, cfg_cluster_tag, "ii") < 0) {
3040*fcf3ce44SJohn Forte 			dsw_error(gettext("SV-disable failed"), NULL);
3041*fcf3ce44SJohn Forte 		}
3042*fcf3ce44SJohn Forte 		cfg_commit(cfg);
3043*fcf3ce44SJohn Forte 	}
3044*fcf3ce44SJohn Forte 
3045*fcf3ce44SJohn Forte 	/* restore old cluster tag, if changed */
3046*fcf3ce44SJohn Forte 	if (old_ctag != NULL)
3047*fcf3ce44SJohn Forte 		cfg_resource(cfg, cfg_cluster_tag = old_ctag);
3048*fcf3ce44SJohn Forte 
3049*fcf3ce44SJohn Forte 	spcs_s_ufree(&parms.status);
3050*fcf3ce44SJohn Forte 	return (0);
3051*fcf3ce44SJohn Forte }
3052*fcf3ce44SJohn Forte 
3053*fcf3ce44SJohn Forte int
3054*fcf3ce44SJohn Forte detach(char *volume)
3055*fcf3ce44SJohn Forte {
3056*fcf3ce44SJohn Forte 	dsw_ioctl_t parms;
3057*fcf3ce44SJohn Forte 	int rc;
3058*fcf3ce44SJohn Forte 
3059*fcf3ce44SJohn Forte 	if (!find_shadow_config(volume, NULL, &parms))
3060*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
3061*fcf3ce44SJohn Forte 						"group"), NULL);
3062*fcf3ce44SJohn Forte 	parms.status = spcs_s_ucreate();
3063*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_ODETACH, &parms);
3064*fcf3ce44SJohn Forte 	if (rc == 0) {
3065*fcf3ce44SJohn Forte 		/* remove overflow from cfg line */
3066*fcf3ce44SJohn Forte 		(void) sprintf(key, "ii.set%d.overflow", setnumber);
3067*fcf3ce44SJohn Forte 		if (cfg_put_cstring(cfg, key, "-", 1) < 0) {
3068*fcf3ce44SJohn Forte 				perror("cfg_put_cstring");
3069*fcf3ce44SJohn Forte 		}
3070*fcf3ce44SJohn Forte 		(void) cfg_commit(cfg);
3071*fcf3ce44SJohn Forte 	} else {
3072*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, gettext("Detach of overflow %s failed"),
3073*fcf3ce44SJohn Forte 				parms.shadow_vol);
3074*fcf3ce44SJohn Forte 		dsw_error(gettext("Failed to detach overflow volume"),
3075*fcf3ce44SJohn Forte 				&parms.status);
3076*fcf3ce44SJohn Forte 	}
3077*fcf3ce44SJohn Forte 	return (rc);
3078*fcf3ce44SJohn Forte }
3079*fcf3ce44SJohn Forte 
3080*fcf3ce44SJohn Forte static void
3081*fcf3ce44SJohn Forte can_disable(char *vol)
3082*fcf3ce44SJohn Forte {
3083*fcf3ce44SJohn Forte 	dsw_stat_t args;
3084*fcf3ce44SJohn Forte 
3085*fcf3ce44SJohn Forte 	if (mounted(vol)) {
3086*fcf3ce44SJohn Forte 		strncpy(args.shadow_vol, vol, DSW_NAMELEN);
3087*fcf3ce44SJohn Forte 		args.shadow_vol[DSW_NAMELEN - 1] = '\0';
3088*fcf3ce44SJohn Forte 		args.status = spcs_s_ucreate();
3089*fcf3ce44SJohn Forte 		if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) != -1 &&
3090*fcf3ce44SJohn Forte 		    (args.stat & DSW_GOLDEN) == 0) {
3091*fcf3ce44SJohn Forte 			errno = EBUSY;
3092*fcf3ce44SJohn Forte 			dsw_error(gettext("Shadow Volume is currently mounted "
3093*fcf3ce44SJohn Forte 			    "and dependent on the master volume"), NULL);
3094*fcf3ce44SJohn Forte 		}
3095*fcf3ce44SJohn Forte 		spcs_s_ufree(&args.status);
3096*fcf3ce44SJohn Forte 	}
3097*fcf3ce44SJohn Forte }
3098*fcf3ce44SJohn Forte 
3099*fcf3ce44SJohn Forte static void
3100*fcf3ce44SJohn Forte clean_up_after_failed_disable(dsw_ioctl_t *parms)
3101*fcf3ce44SJohn Forte {
3102*fcf3ce44SJohn Forte 	char **p;
3103*fcf3ce44SJohn Forte 	dsw_stat_t args;
3104*fcf3ce44SJohn Forte 
3105*fcf3ce44SJohn Forte 	for (p = group_volumes; *p; p++) {
3106*fcf3ce44SJohn Forte 		strncpy(args.shadow_vol, *p, DSW_NAMELEN);
3107*fcf3ce44SJohn Forte 		args.shadow_vol[DSW_NAMELEN - 1] = '\0';
3108*fcf3ce44SJohn Forte 		args.status = spcs_s_ucreate();
3109*fcf3ce44SJohn Forte 		if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1) {
3110*fcf3ce44SJohn Forte 			/* set was successfully disabled */
3111*fcf3ce44SJohn Forte 			if (find_shadow_config(*p, NULL, NULL))
3112*fcf3ce44SJohn Forte 				remove_iiset(setnumber, *p, 0);
3113*fcf3ce44SJohn Forte 		}
3114*fcf3ce44SJohn Forte 		spcs_s_ufree(&args.status);
3115*fcf3ce44SJohn Forte 	}
3116*fcf3ce44SJohn Forte 
3117*fcf3ce44SJohn Forte 	dsw_error(gettext("Some sets in the group failed to disable"),
3118*fcf3ce44SJohn Forte 	    &parms->status);
3119*fcf3ce44SJohn Forte }
3120*fcf3ce44SJohn Forte 
3121*fcf3ce44SJohn Forte int
3122*fcf3ce44SJohn Forte dsw_group_or_single_disable(int argc, char *argv[])
3123*fcf3ce44SJohn Forte {
3124*fcf3ce44SJohn Forte 	int rc = 0;
3125*fcf3ce44SJohn Forte 	char **p;
3126*fcf3ce44SJohn Forte 	dsw_ioctl_t parms;
3127*fcf3ce44SJohn Forte 	int flags = 0;
3128*fcf3ce44SJohn Forte 	dsw_config_t conf;
3129*fcf3ce44SJohn Forte 	int shd_exported = 0;
3130*fcf3ce44SJohn Forte 
3131*fcf3ce44SJohn Forte 	if (argc != 2)
3132*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3133*fcf3ce44SJohn Forte 
3134*fcf3ce44SJohn Forte 	if (group_name) {
3135*fcf3ce44SJohn Forte 		if (find_group_members(group_name) < 1)
3136*fcf3ce44SJohn Forte 			dsw_error(gettext("Group does not exist or "
3137*fcf3ce44SJohn Forte 			    "has no members"), NULL);
3138*fcf3ce44SJohn Forte 		for (p = group_volumes; *p; p++) {
3139*fcf3ce44SJohn Forte 			can_disable(*p);
3140*fcf3ce44SJohn Forte 		}
3141*fcf3ce44SJohn Forte 
3142*fcf3ce44SJohn Forte 		strncpy(parms.shadow_vol, group_name, DSW_NAMELEN);
3143*fcf3ce44SJohn Forte 		if (*group_name)
3144*fcf3ce44SJohn Forte 			flags = CV_IS_GROUP;
3145*fcf3ce44SJohn Forte 	} else {
3146*fcf3ce44SJohn Forte 		if (!find_shadow_config(argv[1], &conf, &parms)) {
3147*fcf3ce44SJohn Forte 			dsw_error(gettext("Volume is not in a Point-in-Time "
3148*fcf3ce44SJohn Forte 			    "Copy group"), NULL);
3149*fcf3ce44SJohn Forte 		}
3150*fcf3ce44SJohn Forte 
3151*fcf3ce44SJohn Forte 		can_disable(argv[1]);
3152*fcf3ce44SJohn Forte 		flags = 0;
3153*fcf3ce44SJohn Forte 	}
3154*fcf3ce44SJohn Forte 
3155*fcf3ce44SJohn Forte 	if (group_name && !*group_name) {
3156*fcf3ce44SJohn Forte 		/* user typed iiadm -g "" -d */
3157*fcf3ce44SJohn Forte 		for (p = group_volumes; *p; p++) {
3158*fcf3ce44SJohn Forte 			parms.status = spcs_s_ucreate();
3159*fcf3ce44SJohn Forte 			parms.flags = flags;
3160*fcf3ce44SJohn Forte 			strncpy(parms.shadow_vol, *p, DSW_NAMELEN);
3161*fcf3ce44SJohn Forte 			rc = do_ioctl(dsw_fd, DSWIOC_DISABLE, &parms);
3162*fcf3ce44SJohn Forte 			if (rc == -1 && errno != DSW_ENOTFOUND)
3163*fcf3ce44SJohn Forte 				dsw_error(gettext("Disable failed"),
3164*fcf3ce44SJohn Forte 				    &parms.status);
3165*fcf3ce44SJohn Forte 			if (!find_shadow_config(*p, NULL, NULL))
3166*fcf3ce44SJohn Forte 				dsw_error(gettext("Volume is not in a Point-in"
3167*fcf3ce44SJohn Forte 				    "-Time Copy group"), &parms.status);
3168*fcf3ce44SJohn Forte 			remove_iiset(setnumber, *p, 0);
3169*fcf3ce44SJohn Forte 			spcs_s_ufree(&parms.status);
3170*fcf3ce44SJohn Forte 			spcs_log("ii", NULL, gettext("Disabled %s"),
3171*fcf3ce44SJohn Forte 			    parms.shadow_vol);
3172*fcf3ce44SJohn Forte 		}
3173*fcf3ce44SJohn Forte 	} else {
3174*fcf3ce44SJohn Forte 		if (is_exported(conf.shadow_vol)) {
3175*fcf3ce44SJohn Forte 			shd_exported = 1;
3176*fcf3ce44SJohn Forte 		}
3177*fcf3ce44SJohn Forte 		if ((strcmp(conf.master_vol, II_IMPORTED_SHADOW) == 0) &&
3178*fcf3ce44SJohn Forte 		    is_exported(conf.shadow_vol)) {
3179*fcf3ce44SJohn Forte 			dsw_error(gettext(
3180*fcf3ce44SJohn Forte 			"Imported shadow not disabled"), NULL);
3181*fcf3ce44SJohn Forte 		}
3182*fcf3ce44SJohn Forte 
3183*fcf3ce44SJohn Forte 		parms.status = spcs_s_ucreate();
3184*fcf3ce44SJohn Forte 		parms.flags = flags;
3185*fcf3ce44SJohn Forte 		rc = do_ioctl(dsw_fd, DSWIOC_DISABLE, &parms);
3186*fcf3ce44SJohn Forte 		if (rc == -1 && errno != DSW_ENOTFOUND) {
3187*fcf3ce44SJohn Forte 			if (errno == DSW_EDISABLE) {
3188*fcf3ce44SJohn Forte 				/*
3189*fcf3ce44SJohn Forte 				 * one or more sets within the group
3190*fcf3ce44SJohn Forte 				 * couldn't disable
3191*fcf3ce44SJohn Forte 				 */
3192*fcf3ce44SJohn Forte 				clean_up_after_failed_disable(&parms);
3193*fcf3ce44SJohn Forte 			} else {
3194*fcf3ce44SJohn Forte 				dsw_error(gettext("Disable failed"),
3195*fcf3ce44SJohn Forte 				    &parms.status);
3196*fcf3ce44SJohn Forte 			}
3197*fcf3ce44SJohn Forte 		}
3198*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, gettext("Disabled %s"), parms.shadow_vol);
3199*fcf3ce44SJohn Forte 	}
3200*fcf3ce44SJohn Forte 
3201*fcf3ce44SJohn Forte 
3202*fcf3ce44SJohn Forte 	if (group_name && *group_name) {
3203*fcf3ce44SJohn Forte 		for (p = group_volumes; *p; p++) {
3204*fcf3ce44SJohn Forte 			if (!find_shadow_config(*p, NULL, NULL)) {
3205*fcf3ce44SJohn Forte 				/* argh! */
3206*fcf3ce44SJohn Forte 				fprintf(stderr, gettext("Volume '%s' is not "
3207*fcf3ce44SJohn Forte 				    "in a Point-in-Time Copy group"), *p);
3208*fcf3ce44SJohn Forte 			} else {
3209*fcf3ce44SJohn Forte 				remove_iiset(setnumber, *p, 0);
3210*fcf3ce44SJohn Forte 			}
3211*fcf3ce44SJohn Forte 		}
3212*fcf3ce44SJohn Forte 	} else if (!group_name) {
3213*fcf3ce44SJohn Forte 		if (!find_shadow_config(argv[1], NULL, NULL)) {
3214*fcf3ce44SJohn Forte 			/* argh! */
3215*fcf3ce44SJohn Forte 			dsw_error(gettext("Volume is not in a Point-in-Time "
3216*fcf3ce44SJohn Forte 			    "Copy group"), NULL);
3217*fcf3ce44SJohn Forte 		}
3218*fcf3ce44SJohn Forte 
3219*fcf3ce44SJohn Forte 		remove_iiset(setnumber, argv[1], shd_exported);
3220*fcf3ce44SJohn Forte 	}
3221*fcf3ce44SJohn Forte 
3222*fcf3ce44SJohn Forte 	return (0);
3223*fcf3ce44SJohn Forte }
3224*fcf3ce44SJohn Forte 
3225*fcf3ce44SJohn Forte int
3226*fcf3ce44SJohn Forte dsw_group_or_single_op(int argc, char *argv[], int (*op)(char *))
3227*fcf3ce44SJohn Forte {
3228*fcf3ce44SJohn Forte 	int rc = 0;
3229*fcf3ce44SJohn Forte 
3230*fcf3ce44SJohn Forte 	if (argc != 2)
3231*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3232*fcf3ce44SJohn Forte 
3233*fcf3ce44SJohn Forte 	if (group_name) {
3234*fcf3ce44SJohn Forte 		if (find_group_members(group_name) < 1)
3235*fcf3ce44SJohn Forte 			dsw_error(gettext("Group does not exist or "
3236*fcf3ce44SJohn Forte 				"has no members"),
3237*fcf3ce44SJohn Forte 						NULL);
3238*fcf3ce44SJohn Forte 		for (; *group_volumes; group_volumes++)
3239*fcf3ce44SJohn Forte 			rc |= (*op)(*group_volumes);
3240*fcf3ce44SJohn Forte 	} else {
3241*fcf3ce44SJohn Forte 		rc = (*op)(argv[1]);
3242*fcf3ce44SJohn Forte 	}
3243*fcf3ce44SJohn Forte 	return (rc);
3244*fcf3ce44SJohn Forte }
3245*fcf3ce44SJohn Forte 
3246*fcf3ce44SJohn Forte void
3247*fcf3ce44SJohn Forte dsw_list_clusters(char *cluster)
3248*fcf3ce44SJohn Forte {
3249*fcf3ce44SJohn Forte 	dsw_aioctl_t *acopy_args;
3250*fcf3ce44SJohn Forte 	int rc, i, count;
3251*fcf3ce44SJohn Forte 	char *ptr;
3252*fcf3ce44SJohn Forte 
3253*fcf3ce44SJohn Forte 	if ((count = do_ioctl(dsw_fd, DSWIOC_LISTLEN, NULL)) < 0)
3254*fcf3ce44SJohn Forte 		dsw_error("DSWIOC_LISTLEN", NULL);
3255*fcf3ce44SJohn Forte 
3256*fcf3ce44SJohn Forte 	acopy_args = malloc(sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
3257*fcf3ce44SJohn Forte 	if (acopy_args == NULL)
3258*fcf3ce44SJohn Forte 		dsw_error(gettext("Can't get memory for list enquiry"), NULL);
3259*fcf3ce44SJohn Forte 
3260*fcf3ce44SJohn Forte 	bzero(acopy_args, sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
3261*fcf3ce44SJohn Forte 	acopy_args->count = count;
3262*fcf3ce44SJohn Forte 	acopy_args->flags = 0;
3263*fcf3ce44SJohn Forte 	acopy_args->status = spcs_s_ucreate();
3264*fcf3ce44SJohn Forte 	if (cluster)
3265*fcf3ce44SJohn Forte 		strncpy(acopy_args->shadow_vol, cluster, DSW_NAMELEN);
3266*fcf3ce44SJohn Forte 
3267*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_CLIST, acopy_args);
3268*fcf3ce44SJohn Forte 	if (rc == -1)
3269*fcf3ce44SJohn Forte 		dsw_error(gettext("Cluster list access failure"),
3270*fcf3ce44SJohn Forte 		    &acopy_args->status);
3271*fcf3ce44SJohn Forte 
3272*fcf3ce44SJohn Forte 	acopy_args->shadow_vol[DSW_NAMELEN*acopy_args->count] = NULL;
3273*fcf3ce44SJohn Forte 
3274*fcf3ce44SJohn Forte 	if (cluster) {
3275*fcf3ce44SJohn Forte 		printf(gettext("Sets in cluster resource group %s:\n"),
3276*fcf3ce44SJohn Forte 		    cluster);
3277*fcf3ce44SJohn Forte 	} else {
3278*fcf3ce44SJohn Forte 		printf(gettext("Currently configured resource groups\n"));
3279*fcf3ce44SJohn Forte 	}
3280*fcf3ce44SJohn Forte 	for (i = 0, ptr = acopy_args->shadow_vol; *ptr &&
3281*fcf3ce44SJohn Forte 	    i < acopy_args->count; i++, ptr += DSW_NAMELEN) {
3282*fcf3ce44SJohn Forte 		printf("  %-64.64s\n", ptr);
3283*fcf3ce44SJohn Forte 	}
3284*fcf3ce44SJohn Forte }
3285*fcf3ce44SJohn Forte 
3286*fcf3ce44SJohn Forte void
3287*fcf3ce44SJohn Forte dsw_enable(int argc, char *argv[])
3288*fcf3ce44SJohn Forte {
3289*fcf3ce44SJohn Forte 	if (argc != 5)
3290*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3291*fcf3ce44SJohn Forte 
3292*fcf3ce44SJohn Forte 	enable(argv[1], argv[2], argv[3], argv[4]);
3293*fcf3ce44SJohn Forte 	exit(0);
3294*fcf3ce44SJohn Forte }
3295*fcf3ce44SJohn Forte 
3296*fcf3ce44SJohn Forte 
3297*fcf3ce44SJohn Forte void
3298*fcf3ce44SJohn Forte dsw_disable(int argc, char *argv[])
3299*fcf3ce44SJohn Forte {
3300*fcf3ce44SJohn Forte 	(void) dsw_group_or_single_disable(argc, argv);
3301*fcf3ce44SJohn Forte 	exit(0);
3302*fcf3ce44SJohn Forte }
3303*fcf3ce44SJohn Forte 
3304*fcf3ce44SJohn Forte 
3305*fcf3ce44SJohn Forte void
3306*fcf3ce44SJohn Forte dsw_copy_to_shadow(int argc, char *argv[])
3307*fcf3ce44SJohn Forte {
3308*fcf3ce44SJohn Forte 	char	**volume_list;
3309*fcf3ce44SJohn Forte 
3310*fcf3ce44SJohn Forte 	if (argc != 2)
3311*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3312*fcf3ce44SJohn Forte 	if (group_name == NULL)
3313*fcf3ce44SJohn Forte 		volume_list = ++argv;
3314*fcf3ce44SJohn Forte 	else {
3315*fcf3ce44SJohn Forte 		if (find_group_members(group_name) < 1)
3316*fcf3ce44SJohn Forte 			dsw_error(gettext("Group does not exist or "
3317*fcf3ce44SJohn Forte 				"has no members"),
3318*fcf3ce44SJohn Forte 						NULL);
3319*fcf3ce44SJohn Forte 		volume_list = group_volumes;
3320*fcf3ce44SJohn Forte 	}
3321*fcf3ce44SJohn Forte 
3322*fcf3ce44SJohn Forte 	exit(do_copy(volume_list, Copy, ToShadow, WaitForStart));
3323*fcf3ce44SJohn Forte }
3324*fcf3ce44SJohn Forte 
3325*fcf3ce44SJohn Forte 
3326*fcf3ce44SJohn Forte void
3327*fcf3ce44SJohn Forte dsw_update_shadow(int argc, char *argv[])
3328*fcf3ce44SJohn Forte {
3329*fcf3ce44SJohn Forte 	char	**volume_list;
3330*fcf3ce44SJohn Forte 
3331*fcf3ce44SJohn Forte 	if (argc != 2)
3332*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3333*fcf3ce44SJohn Forte 	if (group_name == NULL)
3334*fcf3ce44SJohn Forte 		volume_list = ++argv;
3335*fcf3ce44SJohn Forte 	else {
3336*fcf3ce44SJohn Forte 		if (find_group_members(group_name) < 1)
3337*fcf3ce44SJohn Forte 			dsw_error(gettext("Group does not exist or "
3338*fcf3ce44SJohn Forte 				"has no members"),
3339*fcf3ce44SJohn Forte 						NULL);
3340*fcf3ce44SJohn Forte 		volume_list = group_volumes;
3341*fcf3ce44SJohn Forte 	}
3342*fcf3ce44SJohn Forte 
3343*fcf3ce44SJohn Forte 	exit(do_copy(volume_list, Update, ToShadow, WaitForStart));
3344*fcf3ce44SJohn Forte }
3345*fcf3ce44SJohn Forte 
3346*fcf3ce44SJohn Forte 
3347*fcf3ce44SJohn Forte void
3348*fcf3ce44SJohn Forte dsw_copy_to_master(int argc, char *argv[])
3349*fcf3ce44SJohn Forte {
3350*fcf3ce44SJohn Forte 	char	**volume_list;
3351*fcf3ce44SJohn Forte 
3352*fcf3ce44SJohn Forte 	if (argc != 2)
3353*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3354*fcf3ce44SJohn Forte 	if (group_name == NULL) {
3355*fcf3ce44SJohn Forte 		volume_list = ++argv;
3356*fcf3ce44SJohn Forte 		check_action(gettext("Overwrite master with shadow volume?"));
3357*fcf3ce44SJohn Forte 	} else {
3358*fcf3ce44SJohn Forte 		check_action(gettext("Overwrite every"
3359*fcf3ce44SJohn Forte 			" master in this group with its shadow volume?"));
3360*fcf3ce44SJohn Forte 		if (find_group_members(group_name) < 1)
3361*fcf3ce44SJohn Forte 			dsw_error(gettext("Group does not exist or "
3362*fcf3ce44SJohn Forte 				"has no members"),
3363*fcf3ce44SJohn Forte 						NULL);
3364*fcf3ce44SJohn Forte 		volume_list = group_volumes;
3365*fcf3ce44SJohn Forte 	}
3366*fcf3ce44SJohn Forte 
3367*fcf3ce44SJohn Forte 	exit(do_copy(volume_list, Copy, ToMaster, WaitForStart));
3368*fcf3ce44SJohn Forte }
3369*fcf3ce44SJohn Forte 
3370*fcf3ce44SJohn Forte 
3371*fcf3ce44SJohn Forte void
3372*fcf3ce44SJohn Forte dsw_update_master(int argc, char *argv[])
3373*fcf3ce44SJohn Forte {
3374*fcf3ce44SJohn Forte 	char	**volume_list;
3375*fcf3ce44SJohn Forte 
3376*fcf3ce44SJohn Forte 	if (argc != 2)
3377*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3378*fcf3ce44SJohn Forte 	if (group_name == NULL) {
3379*fcf3ce44SJohn Forte 		volume_list = ++argv;
3380*fcf3ce44SJohn Forte 		check_action(gettext("Overwrite master with shadow volume?"));
3381*fcf3ce44SJohn Forte 	} else {
3382*fcf3ce44SJohn Forte 		check_action(gettext("Overwrite every"
3383*fcf3ce44SJohn Forte 			" master in this group with its shadow volume?"));
3384*fcf3ce44SJohn Forte 		if (find_group_members(group_name) < 1)
3385*fcf3ce44SJohn Forte 			dsw_error(gettext("Group does not exist or "
3386*fcf3ce44SJohn Forte 				"has no members"),
3387*fcf3ce44SJohn Forte 						NULL);
3388*fcf3ce44SJohn Forte 		volume_list = group_volumes;
3389*fcf3ce44SJohn Forte 	}
3390*fcf3ce44SJohn Forte 
3391*fcf3ce44SJohn Forte 	exit(do_copy(volume_list, Update, ToMaster, WaitForStart));
3392*fcf3ce44SJohn Forte }
3393*fcf3ce44SJohn Forte 
3394*fcf3ce44SJohn Forte 
3395*fcf3ce44SJohn Forte void
3396*fcf3ce44SJohn Forte dsw_abort_copy(int argc, char *argv[])
3397*fcf3ce44SJohn Forte {
3398*fcf3ce44SJohn Forte 	exit(dsw_group_or_single_op(argc, argv, abort_copy));
3399*fcf3ce44SJohn Forte }
3400*fcf3ce44SJohn Forte 
3401*fcf3ce44SJohn Forte 
3402*fcf3ce44SJohn Forte void
3403*fcf3ce44SJohn Forte dsw_display_status(int argc, char *argv[])
3404*fcf3ce44SJohn Forte {
3405*fcf3ce44SJohn Forte 	dsw_config_t parms;
3406*fcf3ce44SJohn Forte 	int	in_config;
3407*fcf3ce44SJohn Forte 
3408*fcf3ce44SJohn Forte 	if (argc != 2 && argc != 1)
3409*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3410*fcf3ce44SJohn Forte 
3411*fcf3ce44SJohn Forte 	/* "iiadm -i" and "iiadm -i all" are equivalent */
3412*fcf3ce44SJohn Forte 	if (argc == 2 && strcmp("all", argv[1]) != 0) {
3413*fcf3ce44SJohn Forte 		in_config = find_shadow_config(argv[1], &parms, NULL);
3414*fcf3ce44SJohn Forte 		if (!in_config) {
3415*fcf3ce44SJohn Forte 			(void) printf(gettext(
3416*fcf3ce44SJohn Forte 			    "Volume is not in configuration file\n"), NULL);
3417*fcf3ce44SJohn Forte 			(void) fflush(stdout);
3418*fcf3ce44SJohn Forte 			strncpy(parms.shadow_vol, argv[1], DSW_NAMELEN);
3419*fcf3ce44SJohn Forte 			parms.shadow_vol[DSW_NAMELEN] = '\0';
3420*fcf3ce44SJohn Forte 		}
3421*fcf3ce44SJohn Forte 		print_status(&parms, in_config);
3422*fcf3ce44SJohn Forte 	} else if (group_name) {
3423*fcf3ce44SJohn Forte 		if (find_group_members(group_name) < 1)
3424*fcf3ce44SJohn Forte 			dsw_error(gettext("Group does not exist or "
3425*fcf3ce44SJohn Forte 				"has no members"),
3426*fcf3ce44SJohn Forte 						NULL);
3427*fcf3ce44SJohn Forte 		for (; *group_volumes; group_volumes++) {
3428*fcf3ce44SJohn Forte 			in_config = find_shadow_config(*group_volumes,
3429*fcf3ce44SJohn Forte 						&parms, NULL);
3430*fcf3ce44SJohn Forte 			if (in_config)
3431*fcf3ce44SJohn Forte 				print_status(&parms, in_config);
3432*fcf3ce44SJohn Forte 		}
3433*fcf3ce44SJohn Forte 	} else {
3434*fcf3ce44SJohn Forte 		/* perform action for each line of the stored config file */
3435*fcf3ce44SJohn Forte 		for (setnumber = 1;
3436*fcf3ce44SJohn Forte 			!get_dsw_config(setnumber, &parms); setnumber++) {
3437*fcf3ce44SJohn Forte 			switch (check_cluster()) {
3438*fcf3ce44SJohn Forte 			case II_CLUSTER:
3439*fcf3ce44SJohn Forte 			    if ((cfg_cluster_tag) &&
3440*fcf3ce44SJohn Forte 				(strcmp(cfg_cluster_tag, parms.cluster_tag)))
3441*fcf3ce44SJohn Forte 				    continue;
3442*fcf3ce44SJohn Forte 			    break;
3443*fcf3ce44SJohn Forte 			case II_CLUSTER_LCL:
3444*fcf3ce44SJohn Forte 			    if (strlen(parms.cluster_tag))
3445*fcf3ce44SJohn Forte 				    continue;
3446*fcf3ce44SJohn Forte 			    break;
3447*fcf3ce44SJohn Forte 			}
3448*fcf3ce44SJohn Forte 			print_status(&parms, 1);
3449*fcf3ce44SJohn Forte 		}
3450*fcf3ce44SJohn Forte 	}
3451*fcf3ce44SJohn Forte 	exit(0);
3452*fcf3ce44SJohn Forte }
3453*fcf3ce44SJohn Forte 
3454*fcf3ce44SJohn Forte void
3455*fcf3ce44SJohn Forte dsw_display_bitmap(int argc, char *argv[])
3456*fcf3ce44SJohn Forte {
3457*fcf3ce44SJohn Forte 	dsw_config_t parms;
3458*fcf3ce44SJohn Forte 	int	in_config;
3459*fcf3ce44SJohn Forte 
3460*fcf3ce44SJohn Forte 	if (argc != 2)
3461*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3462*fcf3ce44SJohn Forte 
3463*fcf3ce44SJohn Forte 	in_config = find_shadow_config(argv[1], &parms, NULL);
3464*fcf3ce44SJohn Forte 	if (!in_config) {
3465*fcf3ce44SJohn Forte 		(void) printf(gettext(
3466*fcf3ce44SJohn Forte 		    "Volume is not in configuration file\n"), NULL);
3467*fcf3ce44SJohn Forte 		(void) fflush(stdout);
3468*fcf3ce44SJohn Forte 		strncpy(parms.master_vol, argv[1], DSW_NAMELEN);
3469*fcf3ce44SJohn Forte 		parms.master_vol[DSW_NAMELEN] = '\0';
3470*fcf3ce44SJohn Forte 	}
3471*fcf3ce44SJohn Forte 
3472*fcf3ce44SJohn Forte 	bitmap_op(parms.shadow_vol, 1, 0, 0, 0);
3473*fcf3ce44SJohn Forte 	exit(0);
3474*fcf3ce44SJohn Forte }
3475*fcf3ce44SJohn Forte 
3476*fcf3ce44SJohn Forte 
3477*fcf3ce44SJohn Forte /*ARGSUSED*/
3478*fcf3ce44SJohn Forte void
3479*fcf3ce44SJohn Forte dsw_version(int argc, char *argv[])
3480*fcf3ce44SJohn Forte {
3481*fcf3ce44SJohn Forte 	iiversion();
3482*fcf3ce44SJohn Forte 	exit(0);
3483*fcf3ce44SJohn Forte }
3484*fcf3ce44SJohn Forte 
3485*fcf3ce44SJohn Forte void
3486*fcf3ce44SJohn Forte dsw_reset(int argc, char *argv[])
3487*fcf3ce44SJohn Forte {
3488*fcf3ce44SJohn Forte 	exit(dsw_group_or_single_op(argc, argv, reset));
3489*fcf3ce44SJohn Forte }
3490*fcf3ce44SJohn Forte 
3491*fcf3ce44SJohn Forte void
3492*fcf3ce44SJohn Forte dsw_overflow(int argc, char *argv[])
3493*fcf3ce44SJohn Forte {
3494*fcf3ce44SJohn Forte 	if (argc != 2)
3495*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3496*fcf3ce44SJohn Forte 
3497*fcf3ce44SJohn Forte 	exit(overflow(argv[1]));
3498*fcf3ce44SJohn Forte }
3499*fcf3ce44SJohn Forte 
3500*fcf3ce44SJohn Forte void
3501*fcf3ce44SJohn Forte dsw_wait(int argc, char *argv[])
3502*fcf3ce44SJohn Forte {
3503*fcf3ce44SJohn Forte 	exit(dsw_group_or_single_op(argc, argv, wait_for_copy));
3504*fcf3ce44SJohn Forte }
3505*fcf3ce44SJohn Forte 
3506*fcf3ce44SJohn Forte /*ARGSUSED*/
3507*fcf3ce44SJohn Forte void
3508*fcf3ce44SJohn Forte dsw_list_volumes(int argc, char *argv[])
3509*fcf3ce44SJohn Forte {
3510*fcf3ce44SJohn Forte 	if (argc != 1)
3511*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3512*fcf3ce44SJohn Forte 
3513*fcf3ce44SJohn Forte 	list_volumes();
3514*fcf3ce44SJohn Forte 	exit(0);
3515*fcf3ce44SJohn Forte }
3516*fcf3ce44SJohn Forte 
3517*fcf3ce44SJohn Forte void
3518*fcf3ce44SJohn Forte dsw_export(int argc, char *argv[])
3519*fcf3ce44SJohn Forte {
3520*fcf3ce44SJohn Forte 	if (argc != 2)
3521*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3522*fcf3ce44SJohn Forte 
3523*fcf3ce44SJohn Forte 	exit(dsw_group_or_single_op(argc, argv, export));
3524*fcf3ce44SJohn Forte }
3525*fcf3ce44SJohn Forte 
3526*fcf3ce44SJohn Forte void
3527*fcf3ce44SJohn Forte dsw_detach(int argc, char *argv[])
3528*fcf3ce44SJohn Forte {
3529*fcf3ce44SJohn Forte 	(void) dsw_group_or_single_op(argc, argv, detach);
3530*fcf3ce44SJohn Forte 	exit(0);
3531*fcf3ce44SJohn Forte }
3532*fcf3ce44SJohn Forte 
3533*fcf3ce44SJohn Forte void
3534*fcf3ce44SJohn Forte import(char *shadow_volume, char *bitmap_volume)
3535*fcf3ce44SJohn Forte {
3536*fcf3ce44SJohn Forte 	dsw_config_t parms = {0};
3537*fcf3ce44SJohn Forte 	int rc = 0;
3538*fcf3ce44SJohn Forte 	char	shd_dg[DSW_NAMELEN];
3539*fcf3ce44SJohn Forte 	char	bmp_dg[DSW_NAMELEN];
3540*fcf3ce44SJohn Forte 
3541*fcf3ce44SJohn Forte 	/*
3542*fcf3ce44SJohn Forte 	 * If importing a shadow volume and the shadow volume is already
3543*fcf3ce44SJohn Forte 	 * configured, we only support this if we are in a Sun Cluster
3544*fcf3ce44SJohn Forte 	 * and the current user specified a cluster tag of -C local
3545*fcf3ce44SJohn Forte 	 */
3546*fcf3ce44SJohn Forte 	if (find_shadow_config(shadow_volume, &parms, NULL)) {
3547*fcf3ce44SJohn Forte 		dsw_error(gettext("Can't import volume on same node"), NULL);
3548*fcf3ce44SJohn Forte 	}
3549*fcf3ce44SJohn Forte 
3550*fcf3ce44SJohn Forte 	switch (check_cluster()) {
3551*fcf3ce44SJohn Forte 	case II_CLUSTER:
3552*fcf3ce44SJohn Forte 	case II_CLUSTER_LCL:
3553*fcf3ce44SJohn Forte 		(void) check_resource_group(shadow_volume);
3554*fcf3ce44SJohn Forte 		if (cfg_cluster_tag) { /* check all volumes are in same dg */
3555*fcf3ce44SJohn Forte 			if (cfg_dgname(shadow_volume, shd_dg, DSW_NAMELEN)
3556*fcf3ce44SJohn Forte 			    == NULL)
3557*fcf3ce44SJohn Forte 				dsw_error(gettext("Shadow volume not in a"
3558*fcf3ce44SJohn Forte 				    " disk group"), NULL);
3559*fcf3ce44SJohn Forte 			if (cfg_dgname(bitmap_volume, bmp_dg, DSW_NAMELEN)
3560*fcf3ce44SJohn Forte 			    == NULL)
3561*fcf3ce44SJohn Forte 				dsw_error(gettext("Bitmap volume not in a"
3562*fcf3ce44SJohn Forte 				    " disk group"), NULL);
3563*fcf3ce44SJohn Forte 			if (strcmp(bmp_dg, shd_dg) != 0)
3564*fcf3ce44SJohn Forte 				dsw_error(gettext("Bitmap volume not in"
3565*fcf3ce44SJohn Forte 				    " same disk group as shadow set members"),
3566*fcf3ce44SJohn Forte 				    NULL);
3567*fcf3ce44SJohn Forte 		}
3568*fcf3ce44SJohn Forte 		break;
3569*fcf3ce44SJohn Forte 	case II_NOT_CLUSTER:
3570*fcf3ce44SJohn Forte 		/* do nothing */
3571*fcf3ce44SJohn Forte 		break;
3572*fcf3ce44SJohn Forte 	default:
3573*fcf3ce44SJohn Forte 		dsw_error(gettext(
3574*fcf3ce44SJohn Forte 		    "Unexpected return from check_cluster()"), NULL);
3575*fcf3ce44SJohn Forte 	}
3576*fcf3ce44SJohn Forte 
3577*fcf3ce44SJohn Forte 	/* Local configuration volumes */
3578*fcf3ce44SJohn Forte 	if (cfg_load_dsvols(cfg) < 0 || cfg_load_shadows(cfg) < 0) {
3579*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to parse config file"), NULL);
3580*fcf3ce44SJohn Forte 	}
3581*fcf3ce44SJohn Forte 
3582*fcf3ce44SJohn Forte 	reload_vols = LD_DSVOLS | LD_SHADOWS;
3583*fcf3ce44SJohn Forte 	conform_name(&shadow_volume);
3584*fcf3ce44SJohn Forte 	strcpy(parms.master_vol, II_IMPORTED_SHADOW);
3585*fcf3ce44SJohn Forte 	strncpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
3586*fcf3ce44SJohn Forte 	parms.shadow_vol[DSW_NAMELEN-1] = '\0';
3587*fcf3ce44SJohn Forte 	strncpy(parms.bitmap_vol, bitmap_volume, DSW_NAMELEN);
3588*fcf3ce44SJohn Forte 	parms.bitmap_vol[DSW_NAMELEN-1] = '\0';
3589*fcf3ce44SJohn Forte 	parms.flag = DSW_GOLDEN;
3590*fcf3ce44SJohn Forte 
3591*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("Import %s %s"),
3592*fcf3ce44SJohn Forte 	    parms.shadow_vol, parms.bitmap_vol);
3593*fcf3ce44SJohn Forte 	parms.status = spcs_s_ucreate();
3594*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_IMPORT, &parms);
3595*fcf3ce44SJohn Forte 	if (rc == -1) {
3596*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, gettext("Import failed %s %s"),
3597*fcf3ce44SJohn Forte 		    parms.shadow_vol, parms.bitmap_vol);
3598*fcf3ce44SJohn Forte 		dsw_error(gettext("Import failed"), &parms.status);
3599*fcf3ce44SJohn Forte 	}
3600*fcf3ce44SJohn Forte 	if (perform_autosv()) {
3601*fcf3ce44SJohn Forte 		if (cfg_vol_enable(cfg, shadow_volume, cfg_cluster_tag, "ii")
3602*fcf3ce44SJohn Forte 		    < 0) {
3603*fcf3ce44SJohn Forte 			dsw_error(gettext("SV-enable failed"), NULL);
3604*fcf3ce44SJohn Forte 		}
3605*fcf3ce44SJohn Forte 		/* cfg_commit is called by add_cfg_entry below */
3606*fcf3ce44SJohn Forte 	}
3607*fcf3ce44SJohn Forte 	spcs_s_ufree(&parms.status);
3608*fcf3ce44SJohn Forte 	add_cfg_entry(&parms);
3609*fcf3ce44SJohn Forte }
3610*fcf3ce44SJohn Forte 
3611*fcf3ce44SJohn Forte void
3612*fcf3ce44SJohn Forte dsw_import(int argc, char *argv[])
3613*fcf3ce44SJohn Forte {
3614*fcf3ce44SJohn Forte 	if (argc != 3)
3615*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3616*fcf3ce44SJohn Forte 	import(argv[1], argv[2]);
3617*fcf3ce44SJohn Forte 
3618*fcf3ce44SJohn Forte 	exit(0);
3619*fcf3ce44SJohn Forte }
3620*fcf3ce44SJohn Forte 
3621*fcf3ce44SJohn Forte void
3622*fcf3ce44SJohn Forte join(char *shadow_volume, char *bitmap_file)
3623*fcf3ce44SJohn Forte {
3624*fcf3ce44SJohn Forte 	dsw_ioctl_t shd;
3625*fcf3ce44SJohn Forte 	dsw_config_t conf;
3626*fcf3ce44SJohn Forte 	dsw_bitmap_t parms;
3627*fcf3ce44SJohn Forte 	int rc = 0;
3628*fcf3ce44SJohn Forte 	int size;
3629*fcf3ce44SJohn Forte 	FILE *bmpfp;
3630*fcf3ce44SJohn Forte 	uchar_t *shd_bitmap = 0;
3631*fcf3ce44SJohn Forte 	ii_header_t header;
3632*fcf3ce44SJohn Forte 	char dgname[DSW_NAMELEN];
3633*fcf3ce44SJohn Forte 
3634*fcf3ce44SJohn Forte 	if (!find_shadow_config(shadow_volume, &conf, &shd))
3635*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
3636*fcf3ce44SJohn Forte 				"group"), NULL);
3637*fcf3ce44SJohn Forte 
3638*fcf3ce44SJohn Forte 	/* If this is an exportable shadow in the cluster, change ctag */
3639*fcf3ce44SJohn Forte 	if (strlen(conf.cluster_tag) &&
3640*fcf3ce44SJohn Forte 	    (cfg_dgname(shadow_volume, dgname, sizeof (dgname))))
3641*fcf3ce44SJohn Forte 		cfg_resource(cfg, cfg_cluster_tag = strdup(dgname));
3642*fcf3ce44SJohn Forte 
3643*fcf3ce44SJohn Forte 	if (cfg_load_dsvols(cfg) < 0 || cfg_load_shadows(cfg) < 0) {
3644*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to parse config file"), NULL);
3645*fcf3ce44SJohn Forte 	}
3646*fcf3ce44SJohn Forte 	reload_vols = LD_DSVOLS | LD_SHADOWS;
3647*fcf3ce44SJohn Forte 	conform_name(&shadow_volume);
3648*fcf3ce44SJohn Forte 
3649*fcf3ce44SJohn Forte 	if ((bmpfp = fopen(bitmap_file, "r")) == NULL) {
3650*fcf3ce44SJohn Forte 		perror(bitmap_file);
3651*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
3652*fcf3ce44SJohn Forte 		    gettext("Can't open imported bitmap volume\n"));
3653*fcf3ce44SJohn Forte 		exit(1);
3654*fcf3ce44SJohn Forte 	}
3655*fcf3ce44SJohn Forte 
3656*fcf3ce44SJohn Forte 	if (fread(&header, sizeof (header), 1, bmpfp) != 1) {
3657*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
3658*fcf3ce44SJohn Forte 		    gettext("Can't read imported bitmap volume\n"));
3659*fcf3ce44SJohn Forte 		exit(1);
3660*fcf3ce44SJohn Forte 	}
3661*fcf3ce44SJohn Forte 
3662*fcf3ce44SJohn Forte 	/* See if this is a bitmap header */
3663*fcf3ce44SJohn Forte 	switch (header.ii_magic) {
3664*fcf3ce44SJohn Forte 	case DSW_DIRTY:		/* A copy of a enable bitmap volume */
3665*fcf3ce44SJohn Forte 	case DSW_CLEAN:
3666*fcf3ce44SJohn Forte 		check_action(gettext("Use the never imported bitmap?"));
3667*fcf3ce44SJohn Forte 		break;
3668*fcf3ce44SJohn Forte 	case DSW_INVALID:	/* A valid diskable secondary bitmap */
3669*fcf3ce44SJohn Forte 		break;
3670*fcf3ce44SJohn Forte 	default:
3671*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
3672*fcf3ce44SJohn Forte 		    gettext("Secondary bitmap is not a valid bitmap volume\n"));
3673*fcf3ce44SJohn Forte 		exit(1);
3674*fcf3ce44SJohn Forte 	}
3675*fcf3ce44SJohn Forte 
3676*fcf3ce44SJohn Forte 	size = FBA_SIZE(header.ii_copyfba - header.ii_shdfba);
3677*fcf3ce44SJohn Forte 	if ((shd_bitmap = malloc(size)) == NULL) {
3678*fcf3ce44SJohn Forte 		perror("malloc");
3679*fcf3ce44SJohn Forte 		exit(1);
3680*fcf3ce44SJohn Forte 	}
3681*fcf3ce44SJohn Forte 
3682*fcf3ce44SJohn Forte 	if (fseek(bmpfp, FBA_SIZE(header.ii_shdfba), SEEK_SET)) {
3683*fcf3ce44SJohn Forte 		perror("fseek");
3684*fcf3ce44SJohn Forte 		exit(1);
3685*fcf3ce44SJohn Forte 	}
3686*fcf3ce44SJohn Forte 
3687*fcf3ce44SJohn Forte 	if (fread(shd_bitmap, 1, size, bmpfp) != size) {
3688*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
3689*fcf3ce44SJohn Forte 		    gettext("Can't read imported bitmap volume\n"));
3690*fcf3ce44SJohn Forte 		exit(1);
3691*fcf3ce44SJohn Forte 	}
3692*fcf3ce44SJohn Forte 
3693*fcf3ce44SJohn Forte 	(void) fclose(bmpfp);
3694*fcf3ce44SJohn Forte 
3695*fcf3ce44SJohn Forte 	strncpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
3696*fcf3ce44SJohn Forte 	parms.shadow_vol[DSW_NAMELEN-1] = '\0';
3697*fcf3ce44SJohn Forte 	parms.shd_bitmap = shd_bitmap;
3698*fcf3ce44SJohn Forte 	parms.shd_size = size;
3699*fcf3ce44SJohn Forte 	parms.copy_bitmap = NULL;
3700*fcf3ce44SJohn Forte 	parms.copy_size = 0;
3701*fcf3ce44SJohn Forte 
3702*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("Join %s %s"),
3703*fcf3ce44SJohn Forte 	    parms.shadow_vol, bitmap_file);
3704*fcf3ce44SJohn Forte 	parms.status = spcs_s_ucreate();
3705*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_JOIN, &parms);
3706*fcf3ce44SJohn Forte 	if (rc == -1) {
3707*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, gettext("Join failed %s %s"),
3708*fcf3ce44SJohn Forte 		    parms.shadow_vol, bitmap_file);
3709*fcf3ce44SJohn Forte 		dsw_error(gettext("Join failed"), &parms.status);
3710*fcf3ce44SJohn Forte 	}
3711*fcf3ce44SJohn Forte 	if (perform_autosv()) {
3712*fcf3ce44SJohn Forte 		rc = cfg_vol_enable(cfg, shadow_volume, cfg_cluster_tag, "ii");
3713*fcf3ce44SJohn Forte 		if (rc < 0) {
3714*fcf3ce44SJohn Forte 			dsw_error(gettext("SV-enable failed"), NULL);
3715*fcf3ce44SJohn Forte 		}
3716*fcf3ce44SJohn Forte 		cfg_commit(cfg);
3717*fcf3ce44SJohn Forte 	}
3718*fcf3ce44SJohn Forte 	spcs_s_ufree(&parms.status);
3719*fcf3ce44SJohn Forte }
3720*fcf3ce44SJohn Forte 
3721*fcf3ce44SJohn Forte int
3722*fcf3ce44SJohn Forte params(char *shadow_volume)
3723*fcf3ce44SJohn Forte {
3724*fcf3ce44SJohn Forte 	char *delay = param_delay;
3725*fcf3ce44SJohn Forte 	char *unit = param_unit;
3726*fcf3ce44SJohn Forte 	dsw_copyp_t parms;
3727*fcf3ce44SJohn Forte 	int rc = 0;
3728*fcf3ce44SJohn Forte 	int get = 0;
3729*fcf3ce44SJohn Forte 	int new_delay;
3730*fcf3ce44SJohn Forte 	int new_unit;
3731*fcf3ce44SJohn Forte 
3732*fcf3ce44SJohn Forte 	strncpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
3733*fcf3ce44SJohn Forte 	parms.shadow_vol[DSW_NAMELEN-1] = '\0';
3734*fcf3ce44SJohn Forte 	if (delay == NULL || unit == NULL) {
3735*fcf3ce44SJohn Forte 		get = 1;
3736*fcf3ce44SJohn Forte 		parms.copy_delay = -1;
3737*fcf3ce44SJohn Forte 		parms.copy_unit = -1;
3738*fcf3ce44SJohn Forte 	} else {
3739*fcf3ce44SJohn Forte 		new_delay = parms.copy_delay = convert_int(delay);
3740*fcf3ce44SJohn Forte 		new_unit = parms.copy_unit = convert_int(unit);
3741*fcf3ce44SJohn Forte 	}
3742*fcf3ce44SJohn Forte 
3743*fcf3ce44SJohn Forte 	parms.status = spcs_s_ucreate();
3744*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_COPYP, &parms);
3745*fcf3ce44SJohn Forte 	if (rc == -1) {
3746*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
3747*fcf3ce44SJohn Forte 		    gettext("Parameter ranges are delay(%d - %d), "
3748*fcf3ce44SJohn Forte 		    "units(%d - %d)\n"), MIN_THROTTLE_DELAY, MAX_THROTTLE_DELAY,
3749*fcf3ce44SJohn Forte 		    MIN_THROTTLE_UNIT, MAX_THROTTLE_UNIT);
3750*fcf3ce44SJohn Forte 		dsw_error(gettext("Set Copy Parameters failed"), &parms.status);
3751*fcf3ce44SJohn Forte 	}
3752*fcf3ce44SJohn Forte 	if (!get)
3753*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, gettext("Changed copy parameters %s from "
3754*fcf3ce44SJohn Forte 		    "%d %d to %d %d"), parms.shadow_vol, parms.copy_delay,
3755*fcf3ce44SJohn Forte 		    parms.copy_unit, new_delay, new_unit);
3756*fcf3ce44SJohn Forte 	else
3757*fcf3ce44SJohn Forte 		(void) printf(gettext("volume: %s\ncopy delay: %d\ncopy unit:"
3758*fcf3ce44SJohn Forte 		    " %d\n"), parms.shadow_vol, parms.copy_delay,
3759*fcf3ce44SJohn Forte 		    parms.copy_unit);
3760*fcf3ce44SJohn Forte 	spcs_s_ufree(&parms.status);
3761*fcf3ce44SJohn Forte 	return (0);
3762*fcf3ce44SJohn Forte }
3763*fcf3ce44SJohn Forte 
3764*fcf3ce44SJohn Forte static void
3765*fcf3ce44SJohn Forte do_attach(dsw_config_t *parms)
3766*fcf3ce44SJohn Forte {
3767*fcf3ce44SJohn Forte 	dsw_config_t io;
3768*fcf3ce44SJohn Forte 	int rc;
3769*fcf3ce44SJohn Forte 	int check = 0;
3770*fcf3ce44SJohn Forte 
3771*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, gettext("Attach %s %s"),
3772*fcf3ce44SJohn Forte 		parms->shadow_vol, parms->bitmap_vol);
3773*fcf3ce44SJohn Forte 	parms->status = spcs_s_ucreate();
3774*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_OATTACH, parms);
3775*fcf3ce44SJohn Forte 	if (rc == -1) {
3776*fcf3ce44SJohn Forte 		check = 1;
3777*fcf3ce44SJohn Forte 		/* if overflow() fails, it calls dsw_error to exit */
3778*fcf3ce44SJohn Forte 		(void) overflow(parms->bitmap_vol);
3779*fcf3ce44SJohn Forte 	}
3780*fcf3ce44SJohn Forte 	spcs_s_ufree(&parms->status);
3781*fcf3ce44SJohn Forte 	if (check == 1) {
3782*fcf3ce44SJohn Forte 		if (!find_shadow_config(parms->shadow_vol, &io, NULL))
3783*fcf3ce44SJohn Forte 			dsw_error(
3784*fcf3ce44SJohn Forte 			    gettext("Volume is not in a Point-in-Time Copy "
3785*fcf3ce44SJohn Forte 			    "group"), NULL);
3786*fcf3ce44SJohn Forte 		strncpy(io.bitmap_vol, parms->bitmap_vol, DSW_NAMELEN);
3787*fcf3ce44SJohn Forte 		io.bitmap_vol[DSW_NAMELEN-1] = '\0';
3788*fcf3ce44SJohn Forte 		io.status = spcs_s_ucreate();
3789*fcf3ce44SJohn Forte 		if (do_ioctl(dsw_fd, DSWIOC_OATTACH, &io) == -1) {
3790*fcf3ce44SJohn Forte 			spcs_log("ii", NULL, gettext("Attach failed %s %s"),
3791*fcf3ce44SJohn Forte 			    io.shadow_vol, parms->bitmap_vol);
3792*fcf3ce44SJohn Forte 			dsw_error(gettext("Attach failed"), &io.status);
3793*fcf3ce44SJohn Forte 		}
3794*fcf3ce44SJohn Forte 		spcs_s_ufree(&io.status);
3795*fcf3ce44SJohn Forte 	}
3796*fcf3ce44SJohn Forte }
3797*fcf3ce44SJohn Forte 
3798*fcf3ce44SJohn Forte int
3799*fcf3ce44SJohn Forte attach(char *shadow_volume)
3800*fcf3ce44SJohn Forte {
3801*fcf3ce44SJohn Forte 	dsw_config_t parms;
3802*fcf3ce44SJohn Forte 	dsw_stat_t args;
3803*fcf3ce44SJohn Forte 	char	shd_dg[DSW_NAMELEN];
3804*fcf3ce44SJohn Forte 	char	ovr_dg[DSW_NAMELEN];
3805*fcf3ce44SJohn Forte 
3806*fcf3ce44SJohn Forte 	switch (check_cluster()) {
3807*fcf3ce44SJohn Forte 	case II_CLUSTER:
3808*fcf3ce44SJohn Forte 	case II_CLUSTER_LCL:
3809*fcf3ce44SJohn Forte 		(void) check_resource_group(shadow_volume);
3810*fcf3ce44SJohn Forte 		if (cfg_cluster_tag) { /* check all volumes are in same dg */
3811*fcf3ce44SJohn Forte 			if (cfg_dgname(shadow_volume, shd_dg, DSW_NAMELEN)
3812*fcf3ce44SJohn Forte 			    == NULL)
3813*fcf3ce44SJohn Forte 				dsw_error(gettext("Shadow volume not in a"
3814*fcf3ce44SJohn Forte 				    " disk group"), NULL);
3815*fcf3ce44SJohn Forte 			if (cfg_dgname(overflow_file, ovr_dg, DSW_NAMELEN)
3816*fcf3ce44SJohn Forte 			    == NULL)
3817*fcf3ce44SJohn Forte 				dsw_error(gettext("Overflow volume not in a"
3818*fcf3ce44SJohn Forte 				    " disk group"), NULL);
3819*fcf3ce44SJohn Forte 			if (strcmp(ovr_dg, shd_dg) != 0)
3820*fcf3ce44SJohn Forte 				dsw_error(gettext("Overflow volume not in"
3821*fcf3ce44SJohn Forte 				    " same disk group as shadow set members"),
3822*fcf3ce44SJohn Forte 				    NULL);
3823*fcf3ce44SJohn Forte 		}
3824*fcf3ce44SJohn Forte 		break;
3825*fcf3ce44SJohn Forte 	case II_NOT_CLUSTER:
3826*fcf3ce44SJohn Forte 		/* do nothing */
3827*fcf3ce44SJohn Forte 		break;
3828*fcf3ce44SJohn Forte 	default:
3829*fcf3ce44SJohn Forte 		dsw_error(gettext(
3830*fcf3ce44SJohn Forte 		    "Unexpected return from check_cluster()"), NULL);
3831*fcf3ce44SJohn Forte 	}
3832*fcf3ce44SJohn Forte 
3833*fcf3ce44SJohn Forte 	/* assure that the overflow_file is not an II volume */
3834*fcf3ce44SJohn Forte 	if (find_any_cf_line(overflow_file))
3835*fcf3ce44SJohn Forte 		dsw_error(gettext(
3836*fcf3ce44SJohn Forte 			"Overflow volume is already in a Point-in-Time Copy "
3837*fcf3ce44SJohn Forte 			"group"), NULL);
3838*fcf3ce44SJohn Forte 
3839*fcf3ce44SJohn Forte 	/* use find_shadow_config() to find setnumber */
3840*fcf3ce44SJohn Forte 	if (!find_shadow_config(shadow_volume, &parms, NULL))
3841*fcf3ce44SJohn Forte 		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
3842*fcf3ce44SJohn Forte 			"group"), NULL);
3843*fcf3ce44SJohn Forte 
3844*fcf3ce44SJohn Forte 	/* can only attach an overflow volume to dependent, compact shadow */
3845*fcf3ce44SJohn Forte 	strncpy(args.shadow_vol, shadow_volume, DSW_NAMELEN);
3846*fcf3ce44SJohn Forte 	args.shadow_vol[DSW_NAMELEN-1] = '\0';
3847*fcf3ce44SJohn Forte 
3848*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
3849*fcf3ce44SJohn Forte 	if ((do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1) ||
3850*fcf3ce44SJohn Forte 	    !(args.stat & DSW_TREEMAP))
3851*fcf3ce44SJohn Forte 		dsw_error(gettext("Not a compact dependent shadow"), NULL);
3852*fcf3ce44SJohn Forte 
3853*fcf3ce44SJohn Forte 	/* bitmap_vol is overloaded */
3854*fcf3ce44SJohn Forte 	strncpy(parms.bitmap_vol, overflow_file, DSW_NAMELEN);
3855*fcf3ce44SJohn Forte 	parms.bitmap_vol[DSW_NAMELEN-1] = '\0';
3856*fcf3ce44SJohn Forte 
3857*fcf3ce44SJohn Forte 	do_attach(&parms);
3858*fcf3ce44SJohn Forte 
3859*fcf3ce44SJohn Forte 	/* add overflow to cfg line */
3860*fcf3ce44SJohn Forte 	(void) sprintf(key, "ii.set%d.overflow", setnumber);
3861*fcf3ce44SJohn Forte 	if (cfg_put_cstring(cfg, key, overflow_file,
3862*fcf3ce44SJohn Forte 		    strlen(overflow_file)) < 0) {
3863*fcf3ce44SJohn Forte 		perror("cfg_put_cstring");
3864*fcf3ce44SJohn Forte 	}
3865*fcf3ce44SJohn Forte 	(void) cfg_commit(cfg);
3866*fcf3ce44SJohn Forte 	return (0);
3867*fcf3ce44SJohn Forte }
3868*fcf3ce44SJohn Forte 
3869*fcf3ce44SJohn Forte void
3870*fcf3ce44SJohn Forte dsw_join(int argc, char *argv[])
3871*fcf3ce44SJohn Forte {
3872*fcf3ce44SJohn Forte 	if (argc != 3)
3873*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3874*fcf3ce44SJohn Forte 
3875*fcf3ce44SJohn Forte 	join(argv[1], argv[2]);
3876*fcf3ce44SJohn Forte 	exit(0);
3877*fcf3ce44SJohn Forte }
3878*fcf3ce44SJohn Forte 
3879*fcf3ce44SJohn Forte void
3880*fcf3ce44SJohn Forte dsw_params(int argc, char *argv[])
3881*fcf3ce44SJohn Forte {
3882*fcf3ce44SJohn Forte 	if (argc != 4 && argc != 2 && argc != 0)
3883*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3884*fcf3ce44SJohn Forte 
3885*fcf3ce44SJohn Forte 	if ((argc == 4) || (argc == 2)) {
3886*fcf3ce44SJohn Forte 		param_delay = argv[1];
3887*fcf3ce44SJohn Forte 		param_unit = argv[2];
3888*fcf3ce44SJohn Forte 		if (argc == 4) {
3889*fcf3ce44SJohn Forte 			argv[1] = argv[3];
3890*fcf3ce44SJohn Forte 			argv[2] = NULL;
3891*fcf3ce44SJohn Forte 		}
3892*fcf3ce44SJohn Forte 	}
3893*fcf3ce44SJohn Forte 	exit(dsw_group_or_single_op(2, argv, params));
3894*fcf3ce44SJohn Forte }
3895*fcf3ce44SJohn Forte 
3896*fcf3ce44SJohn Forte /*ARGSUSED*/
3897*fcf3ce44SJohn Forte void
3898*fcf3ce44SJohn Forte dsw_attach(int argc, char *argv[])
3899*fcf3ce44SJohn Forte {
3900*fcf3ce44SJohn Forte 	overflow_file = argv[1];
3901*fcf3ce44SJohn Forte 	argv[1] = argv[2];
3902*fcf3ce44SJohn Forte 	(void) dsw_group_or_single_op(2, argv, attach);
3903*fcf3ce44SJohn Forte 	exit(0);
3904*fcf3ce44SJohn Forte }
3905*fcf3ce44SJohn Forte 
3906*fcf3ce44SJohn Forte /*ARGSUSED*/
3907*fcf3ce44SJohn Forte void
3908*fcf3ce44SJohn Forte dsw_olist(int argc, char *argv[])
3909*fcf3ce44SJohn Forte {
3910*fcf3ce44SJohn Forte 	char	*sp, *overflow_list, **vol;
3911*fcf3ce44SJohn Forte 	int	count, i;
3912*fcf3ce44SJohn Forte 	ENTRY	item, *found;
3913*fcf3ce44SJohn Forte 	char	key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ];
3914*fcf3ce44SJohn Forte 
3915*fcf3ce44SJohn Forte 	overflow_list = get_overflow_list();
3916*fcf3ce44SJohn Forte 
3917*fcf3ce44SJohn Forte 	/* count entries */
3918*fcf3ce44SJohn Forte 	count = 0;
3919*fcf3ce44SJohn Forte 	for (sp = overflow_list; *sp; sp += DSW_NAMELEN) {
3920*fcf3ce44SJohn Forte 		++count;
3921*fcf3ce44SJohn Forte 	}
3922*fcf3ce44SJohn Forte 
3923*fcf3ce44SJohn Forte 	/* create hash (adding room for suspended overflow volumes) */
3924*fcf3ce44SJohn Forte 	if (hcreate(count + 1024) == 0) {
3925*fcf3ce44SJohn Forte 		dsw_error(gettext("Out of memory creating lookup table"), NULL);
3926*fcf3ce44SJohn Forte 		/*NOTREACHED*/
3927*fcf3ce44SJohn Forte 	}
3928*fcf3ce44SJohn Forte 
3929*fcf3ce44SJohn Forte 	if (count > 0) {
3930*fcf3ce44SJohn Forte 		/* create memory to store copy of list */
3931*fcf3ce44SJohn Forte 		vol = (char **)calloc(count, sizeof (char *));
3932*fcf3ce44SJohn Forte 		if (!vol) {
3933*fcf3ce44SJohn Forte 			dsw_error(
3934*fcf3ce44SJohn Forte 			    gettext("Out of memory creating lookup table"),
3935*fcf3ce44SJohn Forte 			    NULL);
3936*fcf3ce44SJohn Forte 			/*NOTREACHED*/
3937*fcf3ce44SJohn Forte 		}
3938*fcf3ce44SJohn Forte 
3939*fcf3ce44SJohn Forte 		/* fill hash */
3940*fcf3ce44SJohn Forte 		for (i = 0, sp = overflow_list; *sp; sp += DSW_NAMELEN, i++) {
3941*fcf3ce44SJohn Forte 
3942*fcf3ce44SJohn Forte 			/* make copy of string */
3943*fcf3ce44SJohn Forte 			vol[ i ] = (char *)malloc(DSW_NAMELEN + 1);
3944*fcf3ce44SJohn Forte 			strncpy(vol[ i ], sp, DSW_NAMELEN);
3945*fcf3ce44SJohn Forte 			vol[ i ][ DSW_NAMELEN ] = '\0';
3946*fcf3ce44SJohn Forte 
3947*fcf3ce44SJohn Forte 			item.key = vol[ i ];
3948*fcf3ce44SJohn Forte 			item.data = (char *)0;
3949*fcf3ce44SJohn Forte 			(void) hsearch(item, ENTER);
3950*fcf3ce44SJohn Forte 		}
3951*fcf3ce44SJohn Forte 	}
3952*fcf3ce44SJohn Forte 
3953*fcf3ce44SJohn Forte 	/* loop through config file entries */
3954*fcf3ce44SJohn Forte 	i = 0;
3955*fcf3ce44SJohn Forte 	cfg_rewind(cfg, CFG_SEC_CONF);
3956*fcf3ce44SJohn Forte 
3957*fcf3ce44SJohn Forte 	/*CONSTCOND*/
3958*fcf3ce44SJohn Forte 	while (1) {
3959*fcf3ce44SJohn Forte 		++i;
3960*fcf3ce44SJohn Forte 		(void) snprintf(key, CFG_MAX_KEY, "ii.set%d.overflow", i);
3961*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
3962*fcf3ce44SJohn Forte 			break;
3963*fcf3ce44SJohn Forte 		}
3964*fcf3ce44SJohn Forte 
3965*fcf3ce44SJohn Forte 		/* has this set got an overflow volume? */
3966*fcf3ce44SJohn Forte 		if (!*buf) {
3967*fcf3ce44SJohn Forte 			continue;
3968*fcf3ce44SJohn Forte 		}
3969*fcf3ce44SJohn Forte 
3970*fcf3ce44SJohn Forte 		/* look up overflow in hash */
3971*fcf3ce44SJohn Forte 		item.key = buf;
3972*fcf3ce44SJohn Forte 		if (count > 0 && (found = hsearch(item, FIND)) != NULL) {
3973*fcf3ce44SJohn Forte 			if (0 == (int)found->data) {
3974*fcf3ce44SJohn Forte 				(void) printf("%s\n", buf);
3975*fcf3ce44SJohn Forte 				found->data = (char *)1;
3976*fcf3ce44SJohn Forte 				(void) hsearch(*found, ENTER);
3977*fcf3ce44SJohn Forte 			}
3978*fcf3ce44SJohn Forte 		} else {
3979*fcf3ce44SJohn Forte 			/* must be part of a suspended set */
3980*fcf3ce44SJohn Forte 			(void) printf("%s (attached to suspended set)\n", buf);
3981*fcf3ce44SJohn Forte 			item.key = buf;
3982*fcf3ce44SJohn Forte 			item.data = (char *)1;
3983*fcf3ce44SJohn Forte 			(void) hsearch(item, ENTER);
3984*fcf3ce44SJohn Forte 		}
3985*fcf3ce44SJohn Forte 	}
3986*fcf3ce44SJohn Forte 
3987*fcf3ce44SJohn Forte 	exit(0);
3988*fcf3ce44SJohn Forte }
3989*fcf3ce44SJohn Forte 
3990*fcf3ce44SJohn Forte void
3991*fcf3ce44SJohn Forte dsw_ostat(int argc, char *argv[])
3992*fcf3ce44SJohn Forte {
3993*fcf3ce44SJohn Forte 	dsw_ostat_t	args;
3994*fcf3ce44SJohn Forte 	int	stat_flags;
3995*fcf3ce44SJohn Forte 
3996*fcf3ce44SJohn Forte 	if (argc != 2)
3997*fcf3ce44SJohn Forte 		usage(gettext("Incorrect number of arguments"));
3998*fcf3ce44SJohn Forte 
3999*fcf3ce44SJohn Forte 	strncpy(args.overflow_vol, argv[1], DSW_NAMELEN);
4000*fcf3ce44SJohn Forte 	args.overflow_vol[DSW_NAMELEN-1] = '\0';
4001*fcf3ce44SJohn Forte 
4002*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
4003*fcf3ce44SJohn Forte 	if (do_ioctl(dsw_fd, DSWIOC_OSTAT2, &args) == -1)
4004*fcf3ce44SJohn Forte 		dsw_error(gettext("Stat failed"), &args.status);
4005*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
4006*fcf3ce44SJohn Forte 
4007*fcf3ce44SJohn Forte 	if ((args.hversion >= 1) && (args.hmagic == II_OMAGIC)) {
4008*fcf3ce44SJohn Forte 		stat_flags = args.flags;
4009*fcf3ce44SJohn Forte 		if (stat_flags & IIO_CNTR_INVLD)
4010*fcf3ce44SJohn Forte 			(void) printf(gettext("Clean shutdown of volume "
4011*fcf3ce44SJohn Forte 			"sets associated with overflow volume "
4012*fcf3ce44SJohn Forte 			"did not occur.\n"
4013*fcf3ce44SJohn Forte 			"Overflow counters will be inconsistent "
4014*fcf3ce44SJohn Forte 			"until new point-in-time(s) are taken.\n"));
4015*fcf3ce44SJohn Forte 	}
4016*fcf3ce44SJohn Forte 	(void) printf(gettext("Total number of attached shadows: %d\n"),
4017*fcf3ce44SJohn Forte 	    args.drefcnt);
4018*fcf3ce44SJohn Forte 	(void) printf(gettext("Number of currently attached shadows: %d\n"),
4019*fcf3ce44SJohn Forte 	    args.crefcnt);
4020*fcf3ce44SJohn Forte 	(void) printf(gettext("Total number of chunks: %lld\n"), args.nchunks);
4021*fcf3ce44SJohn Forte 	(void) printf(gettext("Number of chunks ever allocated: %lld\n"),
4022*fcf3ce44SJohn Forte 	    args.used);
4023*fcf3ce44SJohn Forte 	(void) printf(gettext("Number of used chunks: %lld\n"),
4024*fcf3ce44SJohn Forte 		(args.nchunks - args.unused));
4025*fcf3ce44SJohn Forte 	(void) printf(gettext("Number of unused chunks: %lld\n"), args.unused);
4026*fcf3ce44SJohn Forte 	exit(0);
4027*fcf3ce44SJohn Forte }
4028*fcf3ce44SJohn Forte 
4029*fcf3ce44SJohn Forte /*ARGSUSED*/
4030*fcf3ce44SJohn Forte void
4031*fcf3ce44SJohn Forte dsw_move_2_group(int argc, char *argv[])
4032*fcf3ce44SJohn Forte {
4033*fcf3ce44SJohn Forte 	dsw_config_t parms;
4034*fcf3ce44SJohn Forte 	dsw_movegrp_t movegrp;
4035*fcf3ce44SJohn Forte 	grptag_t *gdata;
4036*fcf3ce44SJohn Forte 	int waserr = 0;
4037*fcf3ce44SJohn Forte 
4038*fcf3ce44SJohn Forte 	/* handle move to NULL group, or group of all spaces or tabs */
4039*fcf3ce44SJohn Forte 	strncpy(movegrp.new_group, group_name, DSW_NAMELEN);
4040*fcf3ce44SJohn Forte 	if ((strlen(group_name) == 0) || (strcspn(group_name, " \t") == 0)) {
4041*fcf3ce44SJohn Forte 		group_name = "-";
4042*fcf3ce44SJohn Forte 		bzero(movegrp.new_group, DSW_NAMELEN);
4043*fcf3ce44SJohn Forte 		gdata = NULL;
4044*fcf3ce44SJohn Forte 	} else {
4045*fcf3ce44SJohn Forte 		/* get the ctag for this group (if any) */
4046*fcf3ce44SJohn Forte 		gdata = (grptag_t *)nsc_lookup(volhash, group_name);
4047*fcf3ce44SJohn Forte 	}
4048*fcf3ce44SJohn Forte 
4049*fcf3ce44SJohn Forte 	movegrp.status = spcs_s_ucreate();
4050*fcf3ce44SJohn Forte 
4051*fcf3ce44SJohn Forte 	for (++argv; *argv; argv++) {
4052*fcf3ce44SJohn Forte 		if (!find_shadow_config(*argv, &parms, NULL))
4053*fcf3ce44SJohn Forte 			dsw_error(gettext("Volume is not in a Point-in-Time "
4054*fcf3ce44SJohn Forte 					"Copy group"), NULL);
4055*fcf3ce44SJohn Forte 
4056*fcf3ce44SJohn Forte 		/* ensure the ctag matches the group */
4057*fcf3ce44SJohn Forte 		if (gdata && *gdata->ctag) {
4058*fcf3ce44SJohn Forte 			if (strncmp(parms.cluster_tag, gdata->ctag,
4059*fcf3ce44SJohn Forte 			    DSW_NAMELEN) != 0) {
4060*fcf3ce44SJohn Forte 				(void) fprintf(stderr, "%s: %s %s %s\n", cmdnam,
4061*fcf3ce44SJohn Forte 				    gettext("unable to move set"), *argv,
4062*fcf3ce44SJohn Forte 				    gettext("into new group - cluster "
4063*fcf3ce44SJohn Forte 				    "resource mismatch"));
4064*fcf3ce44SJohn Forte 				waserr = 1;
4065*fcf3ce44SJohn Forte 				continue;
4066*fcf3ce44SJohn Forte 			}
4067*fcf3ce44SJohn Forte 		}
4068*fcf3ce44SJohn Forte 
4069*fcf3ce44SJohn Forte 		/* move the set in the kernel */
4070*fcf3ce44SJohn Forte 		strncpy(movegrp.shadow_vol, parms.shadow_vol, DSW_NAMELEN);
4071*fcf3ce44SJohn Forte 		if (do_ioctl(dsw_fd, DSWIOC_MOVEGRP, &movegrp) < 0)
4072*fcf3ce44SJohn Forte 			dsw_error(gettext("Failed to move group in kernel"),
4073*fcf3ce44SJohn Forte 			    NULL);
4074*fcf3ce44SJohn Forte 
4075*fcf3ce44SJohn Forte 		/* now update the config */
4076*fcf3ce44SJohn Forte 		(void) sprintf(key, "ii.set%d.group", setnumber);
4077*fcf3ce44SJohn Forte 		if (cfg_put_cstring(cfg, key, group_name,
4078*fcf3ce44SJohn Forte 		    strlen(group_name)) < 0) {
4079*fcf3ce44SJohn Forte 			perror("cfg_put_cstring");
4080*fcf3ce44SJohn Forte 		}
4081*fcf3ce44SJohn Forte 		(void) cfg_commit(cfg);
4082*fcf3ce44SJohn Forte 	}
4083*fcf3ce44SJohn Forte 	spcs_s_ufree(&movegrp.status);
4084*fcf3ce44SJohn Forte 	cfg_close(cfg);
4085*fcf3ce44SJohn Forte 	exit(waserr);
4086*fcf3ce44SJohn Forte }
4087*fcf3ce44SJohn Forte 
4088*fcf3ce44SJohn Forte void
4089*fcf3ce44SJohn Forte dsw_list_groups()
4090*fcf3ce44SJohn Forte {
4091*fcf3ce44SJohn Forte 	FILE *pfp;
4092*fcf3ce44SJohn Forte 
4093*fcf3ce44SJohn Forte 	if ((pfp = popen("/usr/bin/sort -u", "w")) == NULL) {
4094*fcf3ce44SJohn Forte 		dsw_error(gettext("Can't open sort program"), NULL);
4095*fcf3ce44SJohn Forte 	}
4096*fcf3ce44SJohn Forte 
4097*fcf3ce44SJohn Forte 	(void) fflush(stdout);
4098*fcf3ce44SJohn Forte 	for (setnumber = 1; /*CSTYLED*/; setnumber++) {
4099*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d.group", setnumber);
4100*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
4101*fcf3ce44SJohn Forte 			break;
4102*fcf3ce44SJohn Forte 
4103*fcf3ce44SJohn Forte 		/* skip if shadow set is not in any group */
4104*fcf3ce44SJohn Forte 		if (strcmp(buf, "") == 0)
4105*fcf3ce44SJohn Forte 			continue;
4106*fcf3ce44SJohn Forte 		(void) fprintf(pfp, "%s\n", buf);
4107*fcf3ce44SJohn Forte 	}
4108*fcf3ce44SJohn Forte 	(void) pclose(pfp);
4109*fcf3ce44SJohn Forte }
4110*fcf3ce44SJohn Forte 
4111*fcf3ce44SJohn Forte void
4112*fcf3ce44SJohn Forte dsw_list_group_volumes()
4113*fcf3ce44SJohn Forte {
4114*fcf3ce44SJohn Forte 	FILE *pfp;
4115*fcf3ce44SJohn Forte 
4116*fcf3ce44SJohn Forte 	if (find_group_members(group_name) < 1)
4117*fcf3ce44SJohn Forte 		dsw_error(gettext("Group does not exist or has no members"),
4118*fcf3ce44SJohn Forte 			NULL);
4119*fcf3ce44SJohn Forte 
4120*fcf3ce44SJohn Forte 	if ((pfp = popen("/usr/bin/sort -u", "w")) == NULL) {
4121*fcf3ce44SJohn Forte 		dsw_error(gettext("Can't open sort program"), NULL);
4122*fcf3ce44SJohn Forte 	}
4123*fcf3ce44SJohn Forte 
4124*fcf3ce44SJohn Forte 	(void) fflush(stdout);
4125*fcf3ce44SJohn Forte 	for (; *group_volumes; group_volumes++)
4126*fcf3ce44SJohn Forte 		(void) fprintf(pfp, "%s\n", *group_volumes);
4127*fcf3ce44SJohn Forte 	(void) pclose(pfp);
4128*fcf3ce44SJohn Forte }
4129*fcf3ce44SJohn Forte 
4130*fcf3ce44SJohn Forte static void
4131*fcf3ce44SJohn Forte load_ii_vols(CFGFILE *cfg)
4132*fcf3ce44SJohn Forte {
4133*fcf3ce44SJohn Forte 	int set, entries;
4134*fcf3ce44SJohn Forte 	char *mst, *shd, *buf, **entry;
4135*fcf3ce44SJohn Forte 	char *ctag, *group;
4136*fcf3ce44SJohn Forte 	mstcount_t *mdata;
4137*fcf3ce44SJohn Forte 	shdvol_t *sdata;
4138*fcf3ce44SJohn Forte 	grptag_t *gdata;
4139*fcf3ce44SJohn Forte 	static int whinged = 0;
4140*fcf3ce44SJohn Forte 
4141*fcf3ce44SJohn Forte 	if (volhash) {
4142*fcf3ce44SJohn Forte 		return;
4143*fcf3ce44SJohn Forte 	}
4144*fcf3ce44SJohn Forte 
4145*fcf3ce44SJohn Forte 	volhash = nsc_create_hash();
4146*fcf3ce44SJohn Forte 	cfg_rewind(cfg, CFG_SEC_CONF);
4147*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "ii");
4148*fcf3ce44SJohn Forte 	for (set = 1; set <= entries; set++) {
4149*fcf3ce44SJohn Forte 		buf = entry[set - 1];
4150*fcf3ce44SJohn Forte 
4151*fcf3ce44SJohn Forte 		/* grab master volume name */
4152*fcf3ce44SJohn Forte 		mst = strtok(buf, " ");
4153*fcf3ce44SJohn Forte 		if (!mst) {
4154*fcf3ce44SJohn Forte 			free(buf);
4155*fcf3ce44SJohn Forte 			break;
4156*fcf3ce44SJohn Forte 		}
4157*fcf3ce44SJohn Forte 
4158*fcf3ce44SJohn Forte 		/* grab shadow, group & cnode fields */
4159*fcf3ce44SJohn Forte 		shd = strtok(NULL, " ");
4160*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* bitmap */
4161*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* mode */
4162*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* overflow */
4163*fcf3ce44SJohn Forte 		ctag = strtok(NULL, " ");	/* cnode */
4164*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* options */
4165*fcf3ce44SJohn Forte 		group = strtok(NULL, " ");	/* group */
4166*fcf3ce44SJohn Forte 
4167*fcf3ce44SJohn Forte 		/* Fix optional tags */
4168*fcf3ce44SJohn Forte 		if (ctag)
4169*fcf3ce44SJohn Forte 			ctag += strspn(ctag, "-");
4170*fcf3ce44SJohn Forte 		if (group)
4171*fcf3ce44SJohn Forte 			group += strspn(group, "-");
4172*fcf3ce44SJohn Forte 
4173*fcf3ce44SJohn Forte 		/* If cluster tags don't match, skip record */
4174*fcf3ce44SJohn Forte 		if ((cfg_cluster_tag && strcmp(ctag, cfg_cluster_tag)) ||
4175*fcf3ce44SJohn Forte 		    (!cfg_cluster_tag && strlen(ctag))) {
4176*fcf3ce44SJohn Forte 			free(buf);
4177*fcf3ce44SJohn Forte 			continue;
4178*fcf3ce44SJohn Forte 		}
4179*fcf3ce44SJohn Forte 
4180*fcf3ce44SJohn Forte 		/* master volume, may be duplicates */
4181*fcf3ce44SJohn Forte 		mdata = (mstcount_t *)nsc_lookup(volhash, mst);
4182*fcf3ce44SJohn Forte 		if (mdata) {
4183*fcf3ce44SJohn Forte 			++mdata->count;
4184*fcf3ce44SJohn Forte 		} else {
4185*fcf3ce44SJohn Forte 			mdata = (mstcount_t *)malloc(sizeof (mstcount_t));
4186*fcf3ce44SJohn Forte 			mdata->count = 1;
4187*fcf3ce44SJohn Forte 			(void) nsc_insert_node(volhash, mdata, mst);
4188*fcf3ce44SJohn Forte 		}
4189*fcf3ce44SJohn Forte 
4190*fcf3ce44SJohn Forte 		/* grab shadow volume name */
4191*fcf3ce44SJohn Forte 		sdata = (shdvol_t *)malloc(sizeof (shdvol_t));
4192*fcf3ce44SJohn Forte 		strncpy(sdata->master, mst, DSW_NAMELEN);
4193*fcf3ce44SJohn Forte 		(void) nsc_insert_node(volhash, sdata, shd);
4194*fcf3ce44SJohn Forte 
4195*fcf3ce44SJohn Forte 		/* No need to continue if no groups or ctags */
4196*fcf3ce44SJohn Forte 		if (!group || !*group || !ctag || !*ctag) {
4197*fcf3ce44SJohn Forte 			free(buf);
4198*fcf3ce44SJohn Forte 			continue;
4199*fcf3ce44SJohn Forte 		}
4200*fcf3ce44SJohn Forte 
4201*fcf3ce44SJohn Forte 		gdata = (grptag_t *)nsc_lookup(volhash, group);
4202*fcf3ce44SJohn Forte 		if (gdata) {
4203*fcf3ce44SJohn Forte 			/* group already exists - check ctag */
4204*fcf3ce44SJohn Forte 			if (*ctag &&
4205*fcf3ce44SJohn Forte 			    (strncmp(ctag, gdata->ctag, DSW_NAMELEN) != 0)) {
4206*fcf3ce44SJohn Forte 				if (!whinged) {
4207*fcf3ce44SJohn Forte 					printf(gettext("Warning: multiple "
4208*fcf3ce44SJohn Forte 					    "cluster resource groups "
4209*fcf3ce44SJohn Forte 					    "defined within a single "
4210*fcf3ce44SJohn Forte 					    "I/O group\n"));
4211*fcf3ce44SJohn Forte 					whinged = 1;
4212*fcf3ce44SJohn Forte 				}
4213*fcf3ce44SJohn Forte 			}
4214*fcf3ce44SJohn Forte 		} else {
4215*fcf3ce44SJohn Forte 			gdata = (grptag_t *)malloc(sizeof (grptag_t));
4216*fcf3ce44SJohn Forte 			strncpy(gdata->ctag, ctag, DSW_NAMELEN);
4217*fcf3ce44SJohn Forte 			(void) nsc_insert_node(volhash, gdata, group);
4218*fcf3ce44SJohn Forte 		}
4219*fcf3ce44SJohn Forte 
4220*fcf3ce44SJohn Forte 		free(buf);
4221*fcf3ce44SJohn Forte 	}
4222*fcf3ce44SJohn Forte 
4223*fcf3ce44SJohn Forte 	/* free up any leftovers */
4224*fcf3ce44SJohn Forte 	while (set < entries)
4225*fcf3ce44SJohn Forte 		free(entry[set++]);
4226*fcf3ce44SJohn Forte 	if (entries)
4227*fcf3ce44SJohn Forte 		free(entry);
4228*fcf3ce44SJohn Forte }
4229*fcf3ce44SJohn Forte 
4230*fcf3ce44SJohn Forte static void
4231*fcf3ce44SJohn Forte unload_ii_vols()
4232*fcf3ce44SJohn Forte {
4233*fcf3ce44SJohn Forte 	nsc_remove_all(volhash, free);
4234*fcf3ce44SJohn Forte 	volhash = 0;
4235*fcf3ce44SJohn Forte }
4236*fcf3ce44SJohn Forte 
4237*fcf3ce44SJohn Forte static int
4238*fcf3ce44SJohn Forte perform_autosv()
4239*fcf3ce44SJohn Forte {
4240*fcf3ce44SJohn Forte 	static int result;
4241*fcf3ce44SJohn Forte 	static int calculated = 0;
4242*fcf3ce44SJohn Forte 	int rc;
4243*fcf3ce44SJohn Forte 
4244*fcf3ce44SJohn Forte #ifdef DEBUG
4245*fcf3ce44SJohn Forte 	if (getenv("II_SET_CLUSTER"))
4246*fcf3ce44SJohn Forte 		return (1);
4247*fcf3ce44SJohn Forte #endif
4248*fcf3ce44SJohn Forte 
4249*fcf3ce44SJohn Forte 	if (calculated) {
4250*fcf3ce44SJohn Forte 		return (result);
4251*fcf3ce44SJohn Forte 	}
4252*fcf3ce44SJohn Forte 
4253*fcf3ce44SJohn Forte 	/*
4254*fcf3ce44SJohn Forte 	 * we only perform auto-sv if we're in a sun cluster or if
4255*fcf3ce44SJohn Forte 	 * we're on a standalone system.  I.e. we don't do auto-sv on Harry
4256*fcf3ce44SJohn Forte 	 */
4257*fcf3ce44SJohn Forte 	rc = check_cluster();
4258*fcf3ce44SJohn Forte 
4259*fcf3ce44SJohn Forte 	if (II_NOT_CLUSTER == rc) {
4260*fcf3ce44SJohn Forte 		result = 1;
4261*fcf3ce44SJohn Forte 	} else {
4262*fcf3ce44SJohn Forte 		result = cfg_issuncluster();
4263*fcf3ce44SJohn Forte 	}
4264*fcf3ce44SJohn Forte 
4265*fcf3ce44SJohn Forte 	calculated = 1;
4266*fcf3ce44SJohn Forte 	return (result);
4267*fcf3ce44SJohn Forte }
4268*fcf3ce44SJohn Forte 
4269*fcf3ce44SJohn Forte /*
4270*fcf3ce44SJohn Forte  * Returns true if set has had the shadow volume exported.
4271*fcf3ce44SJohn Forte  * Returns false if shadow volume is not exported, or set is suspended.
4272*fcf3ce44SJohn Forte  */
4273*fcf3ce44SJohn Forte static int
4274*fcf3ce44SJohn Forte is_exported(char *set)
4275*fcf3ce44SJohn Forte {
4276*fcf3ce44SJohn Forte 	dsw_stat_t args;
4277*fcf3ce44SJohn Forte 	int rc;
4278*fcf3ce44SJohn Forte 
4279*fcf3ce44SJohn Forte 	strncpy(args.shadow_vol, set, DSW_NAMELEN);
4280*fcf3ce44SJohn Forte 	args.shadow_vol[DSW_NAMELEN-1] = '\0';
4281*fcf3ce44SJohn Forte 	args.status = spcs_s_ucreate();
4282*fcf3ce44SJohn Forte 
4283*fcf3ce44SJohn Forte 	rc = do_ioctl(dsw_fd, DSWIOC_STAT, &args);
4284*fcf3ce44SJohn Forte 	spcs_s_ufree(&args.status);
4285*fcf3ce44SJohn Forte 
4286*fcf3ce44SJohn Forte 	if (-1 == rc) {
4287*fcf3ce44SJohn Forte 		/* set must be suspended, or being disabled */
4288*fcf3ce44SJohn Forte 		return (0);
4289*fcf3ce44SJohn Forte 	}
4290*fcf3ce44SJohn Forte 
4291*fcf3ce44SJohn Forte 	return ((args.stat & DSW_SHDEXPORT) == DSW_SHDEXPORT);
4292*fcf3ce44SJohn Forte }
4293*fcf3ce44SJohn Forte 
4294*fcf3ce44SJohn Forte static void
4295*fcf3ce44SJohn Forte conform_name(char **path)
4296*fcf3ce44SJohn Forte {
4297*fcf3ce44SJohn Forte 	char *cfgname;
4298*fcf3ce44SJohn Forte 	int rc = cfg_get_canonical_name(cfg, *path, &cfgname);
4299*fcf3ce44SJohn Forte 
4300*fcf3ce44SJohn Forte 	if (rc < 0) {
4301*fcf3ce44SJohn Forte 		dsw_error(gettext("Unable to parse config file"), NULL);
4302*fcf3ce44SJohn Forte 	}
4303*fcf3ce44SJohn Forte 	if (rc) {
4304*fcf3ce44SJohn Forte 		printf("  '%s'\n%s\n  '%s'\n", *path,
4305*fcf3ce44SJohn Forte 		    gettext("is currently configured as"), cfgname);
4306*fcf3ce44SJohn Forte 		check_action(gettext("Perform operation with indicated volume"
4307*fcf3ce44SJohn Forte 		    " name?"));
4308*fcf3ce44SJohn Forte 		*path = cfgname;
4309*fcf3ce44SJohn Forte 		/*
4310*fcf3ce44SJohn Forte 		 * NOTE: *path ought to be deallocated ('free(*path)') after
4311*fcf3ce44SJohn Forte 		 * we're done with it, but since this routine is called just
4312*fcf3ce44SJohn Forte 		 * before we exit, it doesn't really matter
4313*fcf3ce44SJohn Forte 		 */
4314*fcf3ce44SJohn Forte 	}
4315*fcf3ce44SJohn Forte }
4316*fcf3ce44SJohn Forte 
4317*fcf3ce44SJohn Forte /*
4318*fcf3ce44SJohn Forte  * verify_groupname(char *, int);
4319*fcf3ce44SJohn Forte  *
4320*fcf3ce44SJohn Forte  * Check the group name for the following rules:
4321*fcf3ce44SJohn Forte  *	1. The name does not start with a '-'
4322*fcf3ce44SJohn Forte  *	2. The name does not contain any space characters as defined by
4323*fcf3ce44SJohn Forte  *	   isspace(3C).
4324*fcf3ce44SJohn Forte  * If either of these rules are broken, error immediately. The check for a
4325*fcf3ce44SJohn Forte  * leading dash can be skipped if the 'testDash' argument is false. This is to
4326*fcf3ce44SJohn Forte  * allow for the '-g -L' functionality.
4327*fcf3ce44SJohn Forte  *
4328*fcf3ce44SJohn Forte  */
4329*fcf3ce44SJohn Forte static void
4330*fcf3ce44SJohn Forte verify_groupname(char *grp, int testDash)
4331*fcf3ce44SJohn Forte {
4332*fcf3ce44SJohn Forte 	int i;
4333*fcf3ce44SJohn Forte 
4334*fcf3ce44SJohn Forte 	if (testDash && grp[0] == '-') {
4335*fcf3ce44SJohn Forte 		errno = EINVAL;
4336*fcf3ce44SJohn Forte 		dsw_error(gettext("group name cannot start with a '-'"), NULL);
4337*fcf3ce44SJohn Forte 	}
4338*fcf3ce44SJohn Forte 
4339*fcf3ce44SJohn Forte 	for (i = 0; grp[i] != '\0'; i++) {
4340*fcf3ce44SJohn Forte 		if (isspace(grp[i])) {
4341*fcf3ce44SJohn Forte 			errno = EINVAL;
4342*fcf3ce44SJohn Forte 			dsw_error(gettext("group name cannot contain a space"),
4343*fcf3ce44SJohn Forte 			    NULL);
4344*fcf3ce44SJohn Forte 		}
4345*fcf3ce44SJohn Forte 	}
4346*fcf3ce44SJohn Forte }
4347*fcf3ce44SJohn Forte 
4348*fcf3ce44SJohn Forte void
4349*fcf3ce44SJohn Forte check_iishadow(char *shadow_vol) {
4350*fcf3ce44SJohn Forte 	int i;
4351*fcf3ce44SJohn Forte 	int entries;
4352*fcf3ce44SJohn Forte 	char **entry;
4353*fcf3ce44SJohn Forte 	char *shost;
4354*fcf3ce44SJohn Forte 	char *svol;
4355*fcf3ce44SJohn Forte 	char *buf;
4356*fcf3ce44SJohn Forte 	void *librdc;
4357*fcf3ce44SJohn Forte 
4358*fcf3ce44SJohn Forte 	/*
4359*fcf3ce44SJohn Forte 	 * See if librdc is around
4360*fcf3ce44SJohn Forte 	 * If not, we can just return
4361*fcf3ce44SJohn Forte 	 */
4362*fcf3ce44SJohn Forte 	if (librdc = dlopen(RDC_LIB, RTLD_LAZY | RTLD_GLOBAL))
4363*fcf3ce44SJohn Forte 		self_check = (int (*)(char *)) dlsym(librdc, "self_check");
4364*fcf3ce44SJohn Forte 	else {
4365*fcf3ce44SJohn Forte 		return;
4366*fcf3ce44SJohn Forte 	}
4367*fcf3ce44SJohn Forte 
4368*fcf3ce44SJohn Forte 	entry = NULL;
4369*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "sndr");
4370*fcf3ce44SJohn Forte 	for (i = 0; i < entries; i++) {
4371*fcf3ce44SJohn Forte 		buf = entry[i];
4372*fcf3ce44SJohn Forte 
4373*fcf3ce44SJohn Forte 		(void) strtok(buf, " ");	/* phost */
4374*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* primary */
4375*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* pbitmap */
4376*fcf3ce44SJohn Forte 		shost = strtok(NULL, " ");	/* shost */
4377*fcf3ce44SJohn Forte 		svol = strtok(NULL, " ");	/* secondary */
4378*fcf3ce44SJohn Forte 
4379*fcf3ce44SJohn Forte 		if (self_check(shost) && (strcmp(shadow_vol, svol) == 0)) {
4380*fcf3ce44SJohn Forte 			free(buf);
4381*fcf3ce44SJohn Forte 			if (entries)
4382*fcf3ce44SJohn Forte 				free(entry);
4383*fcf3ce44SJohn Forte 			errno = EINVAL;
4384*fcf3ce44SJohn Forte 			dsw_error(gettext(
4385*fcf3ce44SJohn Forte 			    "shadow volume is in use as SNDR secondary volume"),
4386*fcf3ce44SJohn Forte 			    NULL);
4387*fcf3ce44SJohn Forte 		}
4388*fcf3ce44SJohn Forte 		free(buf);
4389*fcf3ce44SJohn Forte 	}
4390*fcf3ce44SJohn Forte 
4391*fcf3ce44SJohn Forte 	(void) dlclose(librdc);
4392*fcf3ce44SJohn Forte 	if (entries)
4393*fcf3ce44SJohn Forte 		free(entry);
4394*fcf3ce44SJohn Forte }
4395