xref: /onnv-gate/usr/src/cmd/avs/dsbitmap/dsbitmap.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #include <sys/types.h>
27*7836SJohn.Forte@Sun.COM #include <sys/stat.h>
28*7836SJohn.Forte@Sun.COM #include <sys/dkio.h>
29*7836SJohn.Forte@Sun.COM #include <sys/vtoc.h>
30*7836SJohn.Forte@Sun.COM #include <sys/mkdev.h>
31*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
32*7836SJohn.Forte@Sun.COM #include <sys/efi_partition.h>
33*7836SJohn.Forte@Sun.COM #endif
34*7836SJohn.Forte@Sun.COM #include <strings.h>
35*7836SJohn.Forte@Sun.COM #include <stdarg.h>
36*7836SJohn.Forte@Sun.COM #include <stdlib.h>
37*7836SJohn.Forte@Sun.COM #include <fcntl.h>
38*7836SJohn.Forte@Sun.COM #include <errno.h>
39*7836SJohn.Forte@Sun.COM #include <stdio.h>
40*7836SJohn.Forte@Sun.COM #include <locale.h>
41*7836SJohn.Forte@Sun.COM #include <unistd.h>
42*7836SJohn.Forte@Sun.COM #include <libgen.h>
43*7836SJohn.Forte@Sun.COM #include <kstat.h>
44*7836SJohn.Forte@Sun.COM 
45*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
46*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_u.h>
47*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
48*7836SJohn.Forte@Sun.COM 
49*7836SJohn.Forte@Sun.COM #include <sys/nsctl/dsw.h>
50*7836SJohn.Forte@Sun.COM #include <sys/nsctl/dsw_dev.h>
51*7836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_io.h>
52*7836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_bitmap.h>
53*7836SJohn.Forte@Sun.COM 
54*7836SJohn.Forte@Sun.COM enum { UNKNOWN = 0, SNDR, II };
55*7836SJohn.Forte@Sun.COM 
56*7836SJohn.Forte@Sun.COM static char *program;
57*7836SJohn.Forte@Sun.COM 
58*7836SJohn.Forte@Sun.COM void
usage(void)59*7836SJohn.Forte@Sun.COM usage(void)
60*7836SJohn.Forte@Sun.COM {
61*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("usage: %s -h\n"), program);
62*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("       %s { -p | -r } data_volume "
63*7836SJohn.Forte@Sun.COM 	    "[bitmap_volume]\n"), program);
64*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("       -h : This usage message\n"));
65*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("       -p : Calculate size of Point in Time "
66*7836SJohn.Forte@Sun.COM 	    "bitmap\n"));
67*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("       -r : Calculate size of Remote Mirror "
68*7836SJohn.Forte@Sun.COM 	    "bitmap\n"));
69*7836SJohn.Forte@Sun.COM }
70*7836SJohn.Forte@Sun.COM 
71*7836SJohn.Forte@Sun.COM 
72*7836SJohn.Forte@Sun.COM static void
message(char * prefix,spcs_s_info_t * status,caddr_t string,va_list ap)73*7836SJohn.Forte@Sun.COM message(char *prefix, spcs_s_info_t *status, caddr_t string, va_list ap)
74*7836SJohn.Forte@Sun.COM {
75*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, "%s: %s: ", program, prefix);
76*7836SJohn.Forte@Sun.COM 	(void) vfprintf(stderr, string, ap);
77*7836SJohn.Forte@Sun.COM 	(void) fprintf(stderr, "\n");
78*7836SJohn.Forte@Sun.COM 
79*7836SJohn.Forte@Sun.COM 	if (status) {
80*7836SJohn.Forte@Sun.COM 		spcs_s_report(*status, stderr);
81*7836SJohn.Forte@Sun.COM 		spcs_s_ufree(status);
82*7836SJohn.Forte@Sun.COM 	}
83*7836SJohn.Forte@Sun.COM }
84*7836SJohn.Forte@Sun.COM 
85*7836SJohn.Forte@Sun.COM 
86*7836SJohn.Forte@Sun.COM static void
error(spcs_s_info_t * status,char * string,...)87*7836SJohn.Forte@Sun.COM error(spcs_s_info_t *status, char *string, ...)
88*7836SJohn.Forte@Sun.COM {
89*7836SJohn.Forte@Sun.COM 	va_list ap;
90*7836SJohn.Forte@Sun.COM 	va_start(ap, string);
91*7836SJohn.Forte@Sun.COM 
92*7836SJohn.Forte@Sun.COM 	message(gettext("error"), status, string, ap);
93*7836SJohn.Forte@Sun.COM 	va_end(ap);
94*7836SJohn.Forte@Sun.COM 	exit(1);
95*7836SJohn.Forte@Sun.COM }
96*7836SJohn.Forte@Sun.COM 
97*7836SJohn.Forte@Sun.COM 
98*7836SJohn.Forte@Sun.COM static void
warn(spcs_s_info_t * status,char * string,...)99*7836SJohn.Forte@Sun.COM warn(spcs_s_info_t *status, char *string, ...)
100*7836SJohn.Forte@Sun.COM {
101*7836SJohn.Forte@Sun.COM 	va_list ap;
102*7836SJohn.Forte@Sun.COM 	va_start(ap, string);
103*7836SJohn.Forte@Sun.COM 
104*7836SJohn.Forte@Sun.COM 	message(gettext("warning"), status, string, ap);
105*7836SJohn.Forte@Sun.COM 	va_end(ap);
106*7836SJohn.Forte@Sun.COM }
107*7836SJohn.Forte@Sun.COM 
108*7836SJohn.Forte@Sun.COM #if defined(_LP64)
109*7836SJohn.Forte@Sun.COM 					/* max value of a "long int" */
110*7836SJohn.Forte@Sun.COM #define	ULONG_MAX	18446744073709551615UL
111*7836SJohn.Forte@Sun.COM #else /* _ILP32 */
112*7836SJohn.Forte@Sun.COM #define	ULONG_MAX	4294967295UL	/* max of "unsigned long int" */
113*7836SJohn.Forte@Sun.COM #endif
114*7836SJohn.Forte@Sun.COM 
115*7836SJohn.Forte@Sun.COM static uint64_t
get_partsize(char * partition)116*7836SJohn.Forte@Sun.COM get_partsize(char *partition)
117*7836SJohn.Forte@Sun.COM {
118*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
119*7836SJohn.Forte@Sun.COM 	struct dk_cinfo dki_info;
120*7836SJohn.Forte@Sun.COM 	struct partition64 p64;
121*7836SJohn.Forte@Sun.COM #endif
122*7836SJohn.Forte@Sun.COM 	struct vtoc vtoc;
123*7836SJohn.Forte@Sun.COM 	uint64_t size;
124*7836SJohn.Forte@Sun.COM 	int fd;
125*7836SJohn.Forte@Sun.COM 	int rc;
126*7836SJohn.Forte@Sun.COM 
127*7836SJohn.Forte@Sun.COM 	if ((fd = open(partition, O_RDONLY)) < 0) {
128*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to open partition, %s: %s"),
129*7836SJohn.Forte@Sun.COM 		    partition, strerror(errno));
130*7836SJohn.Forte@Sun.COM 		/* NOTREACHED */
131*7836SJohn.Forte@Sun.COM 	}
132*7836SJohn.Forte@Sun.COM 
133*7836SJohn.Forte@Sun.COM 	rc = read_vtoc(fd, &vtoc);
134*7836SJohn.Forte@Sun.COM 	if (rc >= 0) {
135*7836SJohn.Forte@Sun.COM 		size = (uint64_t)(ULONG_MAX & vtoc.v_part[rc].p_size);
136*7836SJohn.Forte@Sun.COM 		return (size);
137*7836SJohn.Forte@Sun.COM 	}
138*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
139*7836SJohn.Forte@Sun.COM 	else if (rc != VT_ENOTSUP) {
140*7836SJohn.Forte@Sun.COM #endif
141*7836SJohn.Forte@Sun.COM 		error(NULL,
142*7836SJohn.Forte@Sun.COM 		    gettext("unable to read the vtoc from partition, %s: %s"),
143*7836SJohn.Forte@Sun.COM 		    partition, strerror(errno));
144*7836SJohn.Forte@Sun.COM 		/* NOTREACHED */
145*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
146*7836SJohn.Forte@Sun.COM 	}
147*7836SJohn.Forte@Sun.COM 
148*7836SJohn.Forte@Sun.COM 	/* See if there is an EFI label */
149*7836SJohn.Forte@Sun.COM 	rc = ioctl(fd, DKIOCINFO, &dki_info);
150*7836SJohn.Forte@Sun.COM 	if (rc < 0) {
151*7836SJohn.Forte@Sun.COM 		error(NULL, gettext("unable to get controller info "
152*7836SJohn.Forte@Sun.COM 		    "from partition, %s: %s"),
153*7836SJohn.Forte@Sun.COM 		    partition, strerror(errno));
154*7836SJohn.Forte@Sun.COM 		/* NOTREACHED */
155*7836SJohn.Forte@Sun.COM 	}
156*7836SJohn.Forte@Sun.COM 
157*7836SJohn.Forte@Sun.COM 	bzero(&p64, sizeof (p64));
158*7836SJohn.Forte@Sun.COM 	p64.p_partno = (uint_t)dki_info.dki_partition;
159*7836SJohn.Forte@Sun.COM 	rc = ioctl(fd, DKIOCPARTITION, &p64);
160*7836SJohn.Forte@Sun.COM 	if (rc >= 0) {
161*7836SJohn.Forte@Sun.COM 		size = (uint64_t)p64.p_size;
162*7836SJohn.Forte@Sun.COM 		return (size);
163*7836SJohn.Forte@Sun.COM 	} else {
164*7836SJohn.Forte@Sun.COM 		struct stat64 stb1, stb2;
165*7836SJohn.Forte@Sun.COM 		struct dk_minfo dkm;
166*7836SJohn.Forte@Sun.COM 
167*7836SJohn.Forte@Sun.COM 		/*
168*7836SJohn.Forte@Sun.COM 		 * See if the stat64 for ZFS's zvol matches
169*7836SJohn.Forte@Sun.COM 		 * this file descriptor's fstat64 data.
170*7836SJohn.Forte@Sun.COM 		 */
171*7836SJohn.Forte@Sun.COM 		if (stat64("/devices/pseudo/zfs@0:zfs", &stb1) != 0 ||
172*7836SJohn.Forte@Sun.COM 		    fstat64(fd, &stb2) != 0 ||
173*7836SJohn.Forte@Sun.COM 		    !S_ISCHR(stb1.st_mode) ||
174*7836SJohn.Forte@Sun.COM 		    !S_ISCHR(stb2.st_mode) ||
175*7836SJohn.Forte@Sun.COM 		    major(stb1.st_rdev) != major(stb2.st_rdev)) {
176*7836SJohn.Forte@Sun.COM 			error(NULL,
177*7836SJohn.Forte@Sun.COM 			    gettext("unable to read disk partition, %s: %s"),
178*7836SJohn.Forte@Sun.COM 			    partition, strerror(errno));
179*7836SJohn.Forte@Sun.COM 			/* NOTREACHED */
180*7836SJohn.Forte@Sun.COM 		}
181*7836SJohn.Forte@Sun.COM 
182*7836SJohn.Forte@Sun.COM 		rc = ioctl(fd, DKIOCGMEDIAINFO, (void *)&dkm);
183*7836SJohn.Forte@Sun.COM 		if (rc >= 0) {
184*7836SJohn.Forte@Sun.COM 			size = LE_64(dkm.dki_capacity) *
185*7836SJohn.Forte@Sun.COM 				dkm.dki_lbsize / 512;
186*7836SJohn.Forte@Sun.COM 			return (size);
187*7836SJohn.Forte@Sun.COM 		} else {
188*7836SJohn.Forte@Sun.COM 			error(NULL, gettext("unable to read EFI label "
189*7836SJohn.Forte@Sun.COM 			    "from partition, %s: %s"),
190*7836SJohn.Forte@Sun.COM 			    partition, strerror(errno));
191*7836SJohn.Forte@Sun.COM 			/* NOTREACHED */
192*7836SJohn.Forte@Sun.COM 		}
193*7836SJohn.Forte@Sun.COM 	}
194*7836SJohn.Forte@Sun.COM 	return (size);
195*7836SJohn.Forte@Sun.COM 
196*7836SJohn.Forte@Sun.COM #endif	/* DKIOCPARTITION */
197*7836SJohn.Forte@Sun.COM }
198*7836SJohn.Forte@Sun.COM 
199*7836SJohn.Forte@Sun.COM 
200*7836SJohn.Forte@Sun.COM int
do_sndr(char * volume,char * bitmap)201*7836SJohn.Forte@Sun.COM do_sndr(char *volume, char *bitmap)
202*7836SJohn.Forte@Sun.COM {
203*7836SJohn.Forte@Sun.COM 	uint64_t vblocks;
204*7836SJohn.Forte@Sun.COM 	uint64_t bblocks;
205*7836SJohn.Forte@Sun.COM 	uint64_t bsize_bits;	/* size of the bits alone */
206*7836SJohn.Forte@Sun.COM 	uint64_t bsize_simple;	/* size of the simple bitmap */
207*7836SJohn.Forte@Sun.COM 	uint64_t bsize_diskq;	/* size of the diskq bitmap, 8 bit refcnt */
208*7836SJohn.Forte@Sun.COM 	uint64_t bsize_diskq32;	/* size of the diskq bitmap, 32 bit refcnt */
209*7836SJohn.Forte@Sun.COM 	int rc = 0;
210*7836SJohn.Forte@Sun.COM 
211*7836SJohn.Forte@Sun.COM 	vblocks = get_partsize(volume);
212*7836SJohn.Forte@Sun.COM 	if (bitmap) {
213*7836SJohn.Forte@Sun.COM 		bblocks = get_partsize(bitmap);
214*7836SJohn.Forte@Sun.COM 	}
215*7836SJohn.Forte@Sun.COM 
216*7836SJohn.Forte@Sun.COM 	bsize_bits = BMAP_LOG_BYTES(vblocks);
217*7836SJohn.Forte@Sun.COM 	bsize_bits = (bsize_bits + 511) / 512;
218*7836SJohn.Forte@Sun.COM 
219*7836SJohn.Forte@Sun.COM 	bsize_simple = RDC_BITMAP_FBA + bsize_bits;
220*7836SJohn.Forte@Sun.COM 	bsize_diskq = RDC_BITMAP_FBA + bsize_bits + (BITS_IN_BYTE * bsize_bits);
221*7836SJohn.Forte@Sun.COM 	bsize_diskq32 = RDC_BITMAP_FBA + bsize_bits + (BITS_IN_BYTE *
222*7836SJohn.Forte@Sun.COM 		bsize_bits * sizeof (unsigned int));
223*7836SJohn.Forte@Sun.COM 
224*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("Remote Mirror bitmap sizing\n\n"));
225*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("Data volume (%s) size: %llu blocks\n"),
226*7836SJohn.Forte@Sun.COM 	    volume, vblocks);
227*7836SJohn.Forte@Sun.COM 
228*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("Required bitmap volume size:\n"));
229*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("  Sync replication: %llu blocks\n"),
230*7836SJohn.Forte@Sun.COM 	    bsize_simple);
231*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("  Async replication with memory queue: "
232*7836SJohn.Forte@Sun.COM 	    "%llu blocks\n"), bsize_simple);
233*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("  Async replication with disk queue: "
234*7836SJohn.Forte@Sun.COM 	    "%llu blocks\n"), bsize_diskq);
235*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("  Async replication with disk queue and 32 bit "
236*7836SJohn.Forte@Sun.COM 	    "refcount: %llu blocks\n"), bsize_diskq32);
237*7836SJohn.Forte@Sun.COM 
238*7836SJohn.Forte@Sun.COM 	if (bitmap) {
239*7836SJohn.Forte@Sun.COM 		(void) printf("\n");
240*7836SJohn.Forte@Sun.COM 		(void) printf(gettext("Supplied bitmap volume %s "
241*7836SJohn.Forte@Sun.COM 		    "(%llu blocks)\n"),
242*7836SJohn.Forte@Sun.COM 		    bitmap, bblocks);
243*7836SJohn.Forte@Sun.COM 		if (bblocks >= bsize_diskq32) {
244*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("is large enough for all "
245*7836SJohn.Forte@Sun.COM 			    "replication modes\n"));
246*7836SJohn.Forte@Sun.COM 		} else if (bblocks >= bsize_diskq) {
247*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("is large enough for all "
248*7836SJohn.Forte@Sun.COM 			    "replication modes, but with restricted diskq "
249*7836SJohn.Forte@Sun.COM 			    "reference counts\n"));
250*7836SJohn.Forte@Sun.COM 		} else if (bblocks >= bsize_simple) {
251*7836SJohn.Forte@Sun.COM 			(void) printf(gettext(
252*7836SJohn.Forte@Sun.COM 			    "is large enough for: Sync and Async(memory) "
253*7836SJohn.Forte@Sun.COM 			    "replication modes only\n"));
254*7836SJohn.Forte@Sun.COM 			rc = 3;
255*7836SJohn.Forte@Sun.COM 		} else {
256*7836SJohn.Forte@Sun.COM 			(void) printf(gettext(
257*7836SJohn.Forte@Sun.COM 			    "is not large enough for any replication modes\n"));
258*7836SJohn.Forte@Sun.COM 			rc = 4;
259*7836SJohn.Forte@Sun.COM 		}
260*7836SJohn.Forte@Sun.COM 	}
261*7836SJohn.Forte@Sun.COM 
262*7836SJohn.Forte@Sun.COM 	return (rc);
263*7836SJohn.Forte@Sun.COM }
264*7836SJohn.Forte@Sun.COM 
265*7836SJohn.Forte@Sun.COM 
266*7836SJohn.Forte@Sun.COM /* sizes in bytes */
267*7836SJohn.Forte@Sun.COM #define	KILO	(1024)
268*7836SJohn.Forte@Sun.COM #define	MEGA	(KILO * KILO)
269*7836SJohn.Forte@Sun.COM #define	GIGA	(MEGA * KILO)
270*7836SJohn.Forte@Sun.COM #define	TERA	((uint64_t)((uint64_t)GIGA * (uint64_t)KILO))
271*7836SJohn.Forte@Sun.COM 
272*7836SJohn.Forte@Sun.COM /* rounding function */
273*7836SJohn.Forte@Sun.COM #define	roundup_2n(x, y)	(((x) + ((y) - 1)) & (~y))
274*7836SJohn.Forte@Sun.COM 
275*7836SJohn.Forte@Sun.COM int
do_ii(char * volume,char * bitmap)276*7836SJohn.Forte@Sun.COM do_ii(char *volume, char *bitmap)
277*7836SJohn.Forte@Sun.COM {
278*7836SJohn.Forte@Sun.COM 	const uint64_t int64_bits = sizeof (uint64_t) * BITS_IN_BYTE;
279*7836SJohn.Forte@Sun.COM 	const uint64_t int32_bits = sizeof (uint32_t) * BITS_IN_BYTE;
280*7836SJohn.Forte@Sun.COM 	const uint64_t terablocks = TERA / ((uint64_t)FBA_SIZE(1));
281*7836SJohn.Forte@Sun.COM 	uint64_t vblocks_phys, vblocks;
282*7836SJohn.Forte@Sun.COM 	uint64_t bblocks;
283*7836SJohn.Forte@Sun.COM 	uint64_t bsize_ind;	/* indep and dep not compact */
284*7836SJohn.Forte@Sun.COM 	uint64_t bsize_cdep;	/* compact dep */
285*7836SJohn.Forte@Sun.COM 	int rc = 0;
286*7836SJohn.Forte@Sun.COM 
287*7836SJohn.Forte@Sun.COM 	vblocks_phys = get_partsize(volume);
288*7836SJohn.Forte@Sun.COM 	if (bitmap) {
289*7836SJohn.Forte@Sun.COM 		bblocks = get_partsize(bitmap);
290*7836SJohn.Forte@Sun.COM 	}
291*7836SJohn.Forte@Sun.COM 
292*7836SJohn.Forte@Sun.COM 	/* round up to multiple of DSW_SIZE blocks */
293*7836SJohn.Forte@Sun.COM 	vblocks = roundup_2n(vblocks_phys, DSW_SIZE);
294*7836SJohn.Forte@Sun.COM 	bsize_ind = DSW_SHD_BM_OFFSET + (2 * DSW_BM_FBA_LEN(vblocks));
295*7836SJohn.Forte@Sun.COM 	bsize_cdep = bsize_ind;
296*7836SJohn.Forte@Sun.COM 	bsize_cdep += DSW_BM_FBA_LEN(vblocks) *
297*7836SJohn.Forte@Sun.COM 	    ((vblocks < (uint64_t)(terablocks * DSW_SIZE)) ?
298*7836SJohn.Forte@Sun.COM 	    int32_bits : int64_bits);
299*7836SJohn.Forte@Sun.COM 
300*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("Point in Time bitmap sizing\n\n"));
301*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("Data volume (%s) size: %llu blocks\n"),
302*7836SJohn.Forte@Sun.COM 	    volume, vblocks_phys);
303*7836SJohn.Forte@Sun.COM 
304*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("Required bitmap volume size:\n"));
305*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("  Independent shadow: %llu blocks\n"),
306*7836SJohn.Forte@Sun.COM 	    bsize_ind);
307*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("  Full size dependent shadow: %llu blocks\n"),
308*7836SJohn.Forte@Sun.COM 	    bsize_ind);
309*7836SJohn.Forte@Sun.COM 	(void) printf(gettext("  Compact dependent shadow: %llu blocks\n"),
310*7836SJohn.Forte@Sun.COM 	    bsize_cdep);
311*7836SJohn.Forte@Sun.COM 
312*7836SJohn.Forte@Sun.COM 	if (bitmap) {
313*7836SJohn.Forte@Sun.COM 		(void) printf("\n");
314*7836SJohn.Forte@Sun.COM 		(void) printf(gettext("Supplied bitmap volume %s "
315*7836SJohn.Forte@Sun.COM 		    "(%llu blocks)\n"), bitmap, bblocks);
316*7836SJohn.Forte@Sun.COM 
317*7836SJohn.Forte@Sun.COM 		if (bblocks >= bsize_cdep) {
318*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("is large enough for all types "
319*7836SJohn.Forte@Sun.COM 			    "of shadow volume\n"));
320*7836SJohn.Forte@Sun.COM 		} else if (bblocks >= bsize_ind) {
321*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("is large enough for: "
322*7836SJohn.Forte@Sun.COM 			    "Independent and full size dependent shadow "
323*7836SJohn.Forte@Sun.COM 			    "volumes only\n"));
324*7836SJohn.Forte@Sun.COM 			rc = 6;
325*7836SJohn.Forte@Sun.COM 		} else {
326*7836SJohn.Forte@Sun.COM 			(void) printf(gettext("is not large enough for"
327*7836SJohn.Forte@Sun.COM 			    "any type of shadow volume\n"));
328*7836SJohn.Forte@Sun.COM 			rc = 5;
329*7836SJohn.Forte@Sun.COM 		}
330*7836SJohn.Forte@Sun.COM 	}
331*7836SJohn.Forte@Sun.COM 
332*7836SJohn.Forte@Sun.COM 	return (rc);
333*7836SJohn.Forte@Sun.COM }
334*7836SJohn.Forte@Sun.COM 
335*7836SJohn.Forte@Sun.COM 
336*7836SJohn.Forte@Sun.COM /*
337*7836SJohn.Forte@Sun.COM  * Return codes:
338*7836SJohn.Forte@Sun.COM  *	0 success (if bitmap was supplied it is large enough for all uses)
339*7836SJohn.Forte@Sun.COM  *	1 usage, programing, or access errors
340*7836SJohn.Forte@Sun.COM  *	2 unknown option supplied on command line
341*7836SJohn.Forte@Sun.COM  *	3 SNDR bitmap is not large enough for diskq usage
342*7836SJohn.Forte@Sun.COM  *	4 SNDR bitmap is not large enough for any usage
343*7836SJohn.Forte@Sun.COM  *	5 II bitmap is not large enough for any usage
344*7836SJohn.Forte@Sun.COM  *	6 II bitmap is not large enough for compact dependent usage
345*7836SJohn.Forte@Sun.COM  */
346*7836SJohn.Forte@Sun.COM int
main(int argc,char * argv[])347*7836SJohn.Forte@Sun.COM main(int argc, char *argv[])
348*7836SJohn.Forte@Sun.COM {
349*7836SJohn.Forte@Sun.COM 	extern int optind;
350*7836SJohn.Forte@Sun.COM 	char *volume, *bitmap;
351*7836SJohn.Forte@Sun.COM 	int type = UNKNOWN;
352*7836SJohn.Forte@Sun.COM 	int opt;
353*7836SJohn.Forte@Sun.COM 	int rc = 0;
354*7836SJohn.Forte@Sun.COM 
355*7836SJohn.Forte@Sun.COM 	(void) setlocale(LC_ALL, "");
356*7836SJohn.Forte@Sun.COM 	(void) textdomain("dsbitmap");
357*7836SJohn.Forte@Sun.COM 
358*7836SJohn.Forte@Sun.COM 	program = strdup(basename(argv[0]));
359*7836SJohn.Forte@Sun.COM 
360*7836SJohn.Forte@Sun.COM 	while ((opt = getopt(argc, argv, "hpr")) != EOF) {
361*7836SJohn.Forte@Sun.COM 		switch (opt) {
362*7836SJohn.Forte@Sun.COM 		case 'p':
363*7836SJohn.Forte@Sun.COM 			if (type != UNKNOWN) {
364*7836SJohn.Forte@Sun.COM 				warn(NULL, gettext(
365*7836SJohn.Forte@Sun.COM 				    "cannot specify -p with other options"));
366*7836SJohn.Forte@Sun.COM 				usage();
367*7836SJohn.Forte@Sun.COM 				return (1);
368*7836SJohn.Forte@Sun.COM 			}
369*7836SJohn.Forte@Sun.COM 			type = II;
370*7836SJohn.Forte@Sun.COM 			break;
371*7836SJohn.Forte@Sun.COM 
372*7836SJohn.Forte@Sun.COM 		case 'r':
373*7836SJohn.Forte@Sun.COM 			if (type != UNKNOWN) {
374*7836SJohn.Forte@Sun.COM 				warn(NULL, gettext(
375*7836SJohn.Forte@Sun.COM 				    "cannot specify -r with other options"));
376*7836SJohn.Forte@Sun.COM 				usage();
377*7836SJohn.Forte@Sun.COM 				return (1);
378*7836SJohn.Forte@Sun.COM 			}
379*7836SJohn.Forte@Sun.COM 			type = SNDR;
380*7836SJohn.Forte@Sun.COM 			break;
381*7836SJohn.Forte@Sun.COM 
382*7836SJohn.Forte@Sun.COM 		case 'h':
383*7836SJohn.Forte@Sun.COM 			if (argc != 2) {
384*7836SJohn.Forte@Sun.COM 				warn(NULL, gettext(
385*7836SJohn.Forte@Sun.COM 				    "cannot specify -h with other options"));
386*7836SJohn.Forte@Sun.COM 				rc = 1;
387*7836SJohn.Forte@Sun.COM 			}
388*7836SJohn.Forte@Sun.COM 			usage();
389*7836SJohn.Forte@Sun.COM 			return (rc);
390*7836SJohn.Forte@Sun.COM 			/* NOTREACHED */
391*7836SJohn.Forte@Sun.COM 
392*7836SJohn.Forte@Sun.COM 		default:
393*7836SJohn.Forte@Sun.COM 			usage();
394*7836SJohn.Forte@Sun.COM 			return (2);
395*7836SJohn.Forte@Sun.COM 			/* NOTREACHED */
396*7836SJohn.Forte@Sun.COM 		}
397*7836SJohn.Forte@Sun.COM 	}
398*7836SJohn.Forte@Sun.COM 
399*7836SJohn.Forte@Sun.COM 	if (type == UNKNOWN) {
400*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("one of -p and -r must be specified"));
401*7836SJohn.Forte@Sun.COM 		usage();
402*7836SJohn.Forte@Sun.COM 		return (1);
403*7836SJohn.Forte@Sun.COM 	}
404*7836SJohn.Forte@Sun.COM 
405*7836SJohn.Forte@Sun.COM 	if ((argc - optind) != 1 && (argc - optind) != 2) {
406*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("incorrect number of arguments to %s"),
407*7836SJohn.Forte@Sun.COM 		    (type == SNDR) ? "-r" : "-p");
408*7836SJohn.Forte@Sun.COM 		usage();
409*7836SJohn.Forte@Sun.COM 		return (1);
410*7836SJohn.Forte@Sun.COM 	}
411*7836SJohn.Forte@Sun.COM 
412*7836SJohn.Forte@Sun.COM 	volume = argv[optind];
413*7836SJohn.Forte@Sun.COM 	if ((argc - optind) == 2) {
414*7836SJohn.Forte@Sun.COM 		bitmap = argv[optind+1];
415*7836SJohn.Forte@Sun.COM 	} else {
416*7836SJohn.Forte@Sun.COM 		bitmap = NULL;
417*7836SJohn.Forte@Sun.COM 	}
418*7836SJohn.Forte@Sun.COM 
419*7836SJohn.Forte@Sun.COM 	switch (type) {
420*7836SJohn.Forte@Sun.COM 	case SNDR:
421*7836SJohn.Forte@Sun.COM 		rc = do_sndr(volume, bitmap);
422*7836SJohn.Forte@Sun.COM 		break;
423*7836SJohn.Forte@Sun.COM 
424*7836SJohn.Forte@Sun.COM 	case II:
425*7836SJohn.Forte@Sun.COM 		rc = do_ii(volume, bitmap);
426*7836SJohn.Forte@Sun.COM 		break;
427*7836SJohn.Forte@Sun.COM 
428*7836SJohn.Forte@Sun.COM 	default:
429*7836SJohn.Forte@Sun.COM 		/* cannot happen */
430*7836SJohn.Forte@Sun.COM 		warn(NULL, gettext("one of -p and -r must be specified"));
431*7836SJohn.Forte@Sun.COM 		rc = 1;
432*7836SJohn.Forte@Sun.COM 		break;
433*7836SJohn.Forte@Sun.COM 	}
434*7836SJohn.Forte@Sun.COM 
435*7836SJohn.Forte@Sun.COM 	return (rc);
436*7836SJohn.Forte@Sun.COM }
437