4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
30 #include <sys/mkdev.h>
32 #include <sys/efi_partition.h>
45 #include <sys/unistat/spcs_s.h>
46 #include <sys/unistat/spcs_s_u.h>
47 #include <sys/unistat/spcs_errors.h>
49 #include <sys/nsctl/dsw.h>
50 #include <sys/nsctl/dsw_dev.h>
51 #include <sys/nsctl/rdc_io.h>
52 #include <sys/nsctl/rdc_bitmap.h>
54 enum { UNKNOWN
= 0, SNDR
, II
};
61 (void) printf(gettext("usage: %s -h\n"), program
);
62 (void) printf(gettext(" %s { -p | -r } data_volume "
63 "[bitmap_volume]\n"), program
);
64 (void) printf(gettext(" -h : This usage message\n"));
65 (void) printf(gettext(" -p : Calculate size of Point in Time "
67 (void) printf(gettext(" -r : Calculate size of Remote Mirror "
73 message(char *prefix
, spcs_s_info_t
*status
, caddr_t string
, va_list ap
)
75 (void) fprintf(stderr
, "%s: %s: ", program
, prefix
);
76 (void) vfprintf(stderr
, string
, ap
);
77 (void) fprintf(stderr
, "\n");
80 spcs_s_report(*status
, stderr
);
87 error(spcs_s_info_t
*status
, char *string
, ...)
92 message(gettext("error"), status
, string
, ap
);
99 warn(spcs_s_info_t
*status
, char *string
, ...)
102 va_start(ap
, string
);
104 message(gettext("warning"), status
, string
, ap
);
109 /* max value of a "long int" */
110 #define ULONG_MAX 18446744073709551615UL
112 #define ULONG_MAX 4294967295UL /* max of "unsigned long int" */
116 get_partsize(char *partition
)
118 #ifdef DKIOCPARTITION
119 struct dk_cinfo dki_info
;
120 struct partition64 p64
;
127 if ((fd
= open(partition
, O_RDONLY
)) < 0) {
128 error(NULL
, gettext("unable to open partition, %s: %s"),
129 partition
, strerror(errno
));
133 rc
= read_vtoc(fd
, &vtoc
);
135 size
= (uint64_t)(ULONG_MAX
& vtoc
.v_part
[rc
].p_size
);
138 #ifdef DKIOCPARTITION
139 else if (rc
!= VT_ENOTSUP
) {
142 gettext("unable to read the vtoc from partition, %s: %s"),
143 partition
, strerror(errno
));
145 #ifdef DKIOCPARTITION
148 /* See if there is an EFI label */
149 rc
= ioctl(fd
, DKIOCINFO
, &dki_info
);
151 error(NULL
, gettext("unable to get controller info "
152 "from partition, %s: %s"),
153 partition
, strerror(errno
));
157 bzero(&p64
, sizeof (p64
));
158 p64
.p_partno
= (uint_t
)dki_info
.dki_partition
;
159 rc
= ioctl(fd
, DKIOCPARTITION
, &p64
);
161 size
= (uint64_t)p64
.p_size
;
164 struct stat64 stb1
, stb2
;
168 * See if the stat64 for ZFS's zvol matches
169 * this file descriptor's fstat64 data.
171 if (stat64("/devices/pseudo/zfs@0:zfs", &stb1
) != 0 ||
172 fstat64(fd
, &stb2
) != 0 ||
173 !S_ISCHR(stb1
.st_mode
) ||
174 !S_ISCHR(stb2
.st_mode
) ||
175 major(stb1
.st_rdev
) != major(stb2
.st_rdev
)) {
177 gettext("unable to read disk partition, %s: %s"),
178 partition
, strerror(errno
));
182 rc
= ioctl(fd
, DKIOCGMEDIAINFO
, (void *)&dkm
);
184 size
= LE_64(dkm
.dki_capacity
) *
185 dkm
.dki_lbsize
/ 512;
188 error(NULL
, gettext("unable to read EFI label "
189 "from partition, %s: %s"),
190 partition
, strerror(errno
));
196 #endif /* DKIOCPARTITION */
201 do_sndr(char *volume
, char *bitmap
)
205 uint64_t bsize_bits
; /* size of the bits alone */
206 uint64_t bsize_simple
; /* size of the simple bitmap */
207 uint64_t bsize_diskq
; /* size of the diskq bitmap, 8 bit refcnt */
208 uint64_t bsize_diskq32
; /* size of the diskq bitmap, 32 bit refcnt */
211 vblocks
= get_partsize(volume
);
213 bblocks
= get_partsize(bitmap
);
216 bsize_bits
= BMAP_LOG_BYTES(vblocks
);
217 bsize_bits
= (bsize_bits
+ 511) / 512;
219 bsize_simple
= RDC_BITMAP_FBA
+ bsize_bits
;
220 bsize_diskq
= RDC_BITMAP_FBA
+ bsize_bits
+ (BITS_IN_BYTE
* bsize_bits
);
221 bsize_diskq32
= RDC_BITMAP_FBA
+ bsize_bits
+ (BITS_IN_BYTE
*
222 bsize_bits
* sizeof (unsigned int));
224 (void) printf(gettext("Remote Mirror bitmap sizing\n\n"));
225 (void) printf(gettext("Data volume (%s) size: %llu blocks\n"),
228 (void) printf(gettext("Required bitmap volume size:\n"));
229 (void) printf(gettext(" Sync replication: %llu blocks\n"),
231 (void) printf(gettext(" Async replication with memory queue: "
232 "%llu blocks\n"), bsize_simple
);
233 (void) printf(gettext(" Async replication with disk queue: "
234 "%llu blocks\n"), bsize_diskq
);
235 (void) printf(gettext(" Async replication with disk queue and 32 bit "
236 "refcount: %llu blocks\n"), bsize_diskq32
);
240 (void) printf(gettext("Supplied bitmap volume %s "
243 if (bblocks
>= bsize_diskq32
) {
244 (void) printf(gettext("is large enough for all "
245 "replication modes\n"));
246 } else if (bblocks
>= bsize_diskq
) {
247 (void) printf(gettext("is large enough for all "
248 "replication modes, but with restricted diskq "
249 "reference counts\n"));
250 } else if (bblocks
>= bsize_simple
) {
251 (void) printf(gettext(
252 "is large enough for: Sync and Async(memory) "
253 "replication modes only\n"));
256 (void) printf(gettext(
257 "is not large enough for any replication modes\n"));
268 #define MEGA (KILO * KILO)
269 #define GIGA (MEGA * KILO)
270 #define TERA ((uint64_t)((uint64_t)GIGA * (uint64_t)KILO))
272 /* rounding function */
273 #define roundup_2n(x, y) (((x) + ((y) - 1)) & (~y))
276 do_ii(char *volume
, char *bitmap
)
278 const uint64_t int64_bits
= sizeof (uint64_t) * BITS_IN_BYTE
;
279 const uint64_t int32_bits
= sizeof (uint32_t) * BITS_IN_BYTE
;
280 const uint64_t terablocks
= TERA
/ ((uint64_t)FBA_SIZE(1));
281 uint64_t vblocks_phys
, vblocks
;
283 uint64_t bsize_ind
; /* indep and dep not compact */
284 uint64_t bsize_cdep
; /* compact dep */
287 vblocks_phys
= get_partsize(volume
);
289 bblocks
= get_partsize(bitmap
);
292 /* round up to multiple of DSW_SIZE blocks */
293 vblocks
= roundup_2n(vblocks_phys
, DSW_SIZE
);
294 bsize_ind
= DSW_SHD_BM_OFFSET
+ (2 * DSW_BM_FBA_LEN(vblocks
));
295 bsize_cdep
= bsize_ind
;
296 bsize_cdep
+= DSW_BM_FBA_LEN(vblocks
) *
297 ((vblocks
< (uint64_t)(terablocks
* DSW_SIZE
)) ?
298 int32_bits
: int64_bits
);
300 (void) printf(gettext("Point in Time bitmap sizing\n\n"));
301 (void) printf(gettext("Data volume (%s) size: %llu blocks\n"),
302 volume
, vblocks_phys
);
304 (void) printf(gettext("Required bitmap volume size:\n"));
305 (void) printf(gettext(" Independent shadow: %llu blocks\n"),
307 (void) printf(gettext(" Full size dependent shadow: %llu blocks\n"),
309 (void) printf(gettext(" Compact dependent shadow: %llu blocks\n"),
314 (void) printf(gettext("Supplied bitmap volume %s "
315 "(%llu blocks)\n"), bitmap
, bblocks
);
317 if (bblocks
>= bsize_cdep
) {
318 (void) printf(gettext("is large enough for all types "
319 "of shadow volume\n"));
320 } else if (bblocks
>= bsize_ind
) {
321 (void) printf(gettext("is large enough for: "
322 "Independent and full size dependent shadow "
326 (void) printf(gettext("is not large enough for"
327 "any type of shadow volume\n"));
338 * 0 success (if bitmap was supplied it is large enough for all uses)
339 * 1 usage, programing, or access errors
340 * 2 unknown option supplied on command line
341 * 3 SNDR bitmap is not large enough for diskq usage
342 * 4 SNDR bitmap is not large enough for any usage
343 * 5 II bitmap is not large enough for any usage
344 * 6 II bitmap is not large enough for compact dependent usage
347 main(int argc
, char *argv
[])
350 char *volume
, *bitmap
;
355 (void) setlocale(LC_ALL
, "");
356 (void) textdomain("dsbitmap");
358 program
= strdup(basename(argv
[0]));
360 while ((opt
= getopt(argc
, argv
, "hpr")) != EOF
) {
363 if (type
!= UNKNOWN
) {
365 "cannot specify -p with other options"));
373 if (type
!= UNKNOWN
) {
375 "cannot specify -r with other options"));
385 "cannot specify -h with other options"));
399 if (type
== UNKNOWN
) {
400 warn(NULL
, gettext("one of -p and -r must be specified"));
405 if ((argc
- optind
) != 1 && (argc
- optind
) != 2) {
406 warn(NULL
, gettext("incorrect number of arguments to %s"),
407 (type
== SNDR
) ? "-r" : "-p");
412 volume
= argv
[optind
];
413 if ((argc
- optind
) == 2) {
414 bitmap
= argv
[optind
+1];
421 rc
= do_sndr(volume
, bitmap
);
425 rc
= do_ii(volume
, bitmap
);
430 warn(NULL
, gettext("one of -p and -r must be specified"));