4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Routines to support fssnap subcommand of switchout. See switchout.c for
31 * the real fssnap command.
38 #include <sys/fssnap_if.h>
42 static void fssnap_display_info(ulong_t
, int *, int);
44 #define MAX_INFO_DESCRIPTORS (10)
46 static char *infosubopts
[] = {
47 #define INFO_SNAPSHOT (0)
49 #define INFO_BLKDEV (1)
51 #define INFO_CHARDEV (2)
53 #define INFO_MNTPT (3)
55 #define INFO_STATE (4)
57 #define INFO_BACKPATH (5)
59 #define INFO_BACKSIZE (6)
61 #define INFO_MAXSIZE (7)
63 #define INFO_CREATETIME (8)
65 #define INFO_CHUNKSIZE (9)
70 #define BLOCK_PATH "/dev/" SNAP_BLOCK_NAME "/"
71 #define CHAR_PATH "/dev/" SNAP_CHAR_NAME "/"
73 /* labels are truncated to this many characters when displayed */
74 #define MAX_LABEL_LEN (30)
77 * fssnap_show_status() - display file system snapshot status
79 * displays snapshot information. If mountpoint is set, information is
80 * only displayed for the snapshot (if one exists) on that file system.
81 * If mountpoint is NULL, information is displayed for all snapshots.
83 * If opts is defined, it is parsed as a list of suboptions (via
84 * getsubopt()) corresponding to the options list defined above. These
85 * options determine what data should be displayed and in what order. An
86 * option may appear more than once.
88 * The labels parameter is a boolean that determines whether labels
89 * (internationalized) are displayed before each data element. If it is
90 * 0, labels are not displayed, otherwise they are. The labels parameter
91 * is ignored if brief is nonzero.
93 * The brief parameter is also a boolean and specifies a mode where only
94 * the snapshot number and mount point are displayed, regardless of the
95 * value of labels. This could be used for listing all active snapshots.
97 * Based on these parameters, an order list is created that tells
98 * fssnap_display_info() what info to display and in what order.
100 * Note that when labels are not specified, the assumption is that the
101 * output is made for script readable consumption. For this reason, text
102 * is not I18N'd and numbers are left as bytes instead of converted to KB.
105 fssnap_show_status(char *mountpoint
, char *opts
, int labels
, int brief
)
107 int *order
, orderlen
= MAX_INFO_DESCRIPTORS
+1;
111 kstat_named_t
*highp
;
112 char *suboptions
, *v
, *n
;
116 kslib
= kstat_open();
117 kshigh
= kstat_lookup(kslib
, SNAP_NAME
, 0, FSSNAP_KSTAT_HIGHWATER
);
120 * First check and see if they gave us a mount point or a device
121 * name (ie /dev/fssnap/X or /dev/rfssnap/X).
124 if (strncmp(BLOCK_PATH
, mountpoint
, strlen(BLOCK_PATH
)) == 0 ||
125 strncmp(CHAR_PATH
, mountpoint
, strlen(CHAR_PATH
)) == 0) {
126 n
= strrchr(mountpoint
, '/');
130 num
= (int)strtol(n
, NULL
, 10);
140 order
= (int *)malloc(orderlen
* sizeof (int));
143 gettext("cannot allocate order list.\n"));
147 while (*suboptions
!= '\0') {
149 * -1 means invalid option, MAX_INFO_DESCRIPTORS is
152 order
[i
++] = getsubopt(&suboptions
, infosubopts
, &v
);
154 order
= reallocarray(order
, orderlen
*= 2,
158 gettext("cannot reallocate order "
165 order
[i
] = MAX_INFO_DESCRIPTORS
;
167 order
= (int *)malloc(orderlen
* sizeof (int));
170 gettext("cannot allocate order list.\n"));
173 for (i
= 0; i
<= MAX_INFO_DESCRIPTORS
; i
++)
177 /* check if fssnap module is loaded */
178 if (kshigh
== NULL
) {
183 (void) kstat_read(kslib
, kshigh
, NULL
);
184 highp
= kstat_data_lookup(kshigh
, FSSNAP_KSTAT_HIGHWATER
);
186 /* Loop up to the maximum number of snapshots */
187 for (i
= 0; i
<= highp
->value
.ui32
; i
++) {
188 mnt
= kstat_lookup(kslib
, SNAP_NAME
, i
, FSSNAP_KSTAT_MNTPT
);
190 /* if this snapshot is not allocated, skip to the next */
193 if (kstat_read(kslib
, mnt
, NULL
) == -1)
195 if (mountpoint
!= NULL
) {
196 if ((usenum
&& i
!= num
) ||
197 (!usenum
&& strcmp(mountpoint
, mnt
->ks_data
) != 0))
202 printf("%4d\t%s\n", i
, (char *)mnt
->ks_data
);
204 fssnap_display_info(i
, order
, labels
);
209 fssnap_display_info(ulong_t snapnum
, int *order
, int labels
)
213 kstat_named_t
*numvalp
;
215 u_longlong_t inuse
, size
= 0;
216 char buf
[BUFSIZ
], *first
;
220 kslib
= kstat_open();
221 num
= kstat_lookup(kslib
, SNAP_NAME
, snapnum
, FSSNAP_KSTAT_NUM
);
225 if (kstat_read(kslib
, num
, NULL
) == -1)
228 for (i
= 0; order
[i
] != MAX_INFO_DESCRIPTORS
; i
++) {
232 printf("%-*s: %lu\n", MAX_LABEL_LEN
,
233 gettext("Snapshot number"), snapnum
);
235 printf("%lu\n", snapnum
);
239 printf("%-*s: /dev/%s/%lu\n", MAX_LABEL_LEN
,
240 gettext("Block Device"), SNAP_BLOCK_NAME
,
243 printf("/dev/%s/%lu\n", SNAP_BLOCK_NAME
,
248 printf("%-*s: /dev/%s/%lu\n", MAX_LABEL_LEN
,
249 gettext("Raw Device"), SNAP_CHAR_NAME
,
252 printf("/dev/%s/%lu\n", SNAP_CHAR_NAME
,
257 mnt
= kstat_lookup(kslib
, SNAP_NAME
, snapnum
,
261 gettext("cannot read mount point kstat\n"));
264 if (kstat_read(kslib
, mnt
, NULL
) == -1) {
268 printf("%-*s: %s\n", MAX_LABEL_LEN
,
269 gettext("Mount point"),
270 (char *)mnt
->ks_data
);
272 printf("%s\n", (char *)mnt
->ks_data
);
276 numvalp
= kstat_data_lookup(num
,
277 FSSNAP_KSTAT_NUM_STATE
);
278 if (numvalp
== NULL
) {
280 gettext("cannot read state kstat\n"));
285 printf("%-*s: ", MAX_LABEL_LEN
,
286 gettext("Device state"));
287 switch (numvalp
->value
.i32
) {
288 case 0: printf(gettext("creating\n"));
290 case 1: printf(gettext("idle\n"));
292 case 2: printf(gettext("active\n"));
294 case 3: printf(gettext("disabled\n"));
296 default: printf(gettext("unknown\n"));
300 switch (numvalp
->value
.i32
) {
301 case 0: printf("creating\n");
303 case 1: printf("idle\n");
305 case 2: printf("active\n");
307 case 3: printf("disabled\n");
309 default: printf("unknown\n");
316 /* backing file kstat */
317 back
= kstat_lookup(kslib
, SNAP_NAME
, snapnum
,
318 FSSNAP_KSTAT_BFNAME
);
320 (kstat_read(kslib
, back
, NULL
) == -1) ||
321 (back
->ks_data
== NULL
)) {
323 gettext("cannot read backing file name "
324 "kstat from kernel\n"));
328 printf("%-*s: %s\n", MAX_LABEL_LEN
,
329 gettext("Backing store path"),
330 (char *)back
->ks_data
);
332 printf("%s\n", (char *)back
->ks_data
);
336 numvalp
= kstat_data_lookup(num
,
337 FSSNAP_KSTAT_NUM_BFSIZE
);
338 if (numvalp
== NULL
) {
340 gettext("cannot read backing file size "
341 "kstat from kernel\n"));
345 size
= numvalp
->value
.ui64
;
348 printf("%-*s: %llu KB\n", MAX_LABEL_LEN
,
349 gettext("Backing store size"),
352 printf("%llu\n", size
);
356 numvalp
= kstat_data_lookup(num
,
357 FSSNAP_KSTAT_NUM_MAXSIZE
);
358 if (numvalp
== NULL
) {
360 gettext("cannot read backing file maxsize "
361 "kstat from kernel\n"));
365 printf("%-*s: ", MAX_LABEL_LEN
,
366 gettext("Maximum backing store size"));
368 if (numvalp
->value
.ui64
== 0LL)
369 printf(gettext("Unlimited\n"));
372 numvalp
->value
.ui64
/ 1024LL);
374 printf("%llu\n", numvalp
->value
.ui64
);
378 case INFO_CREATETIME
:
380 /* snapshot creation time */
385 numvalp
= kstat_data_lookup(num
,
386 FSSNAP_KSTAT_NUM_CREATETIME
);
387 if (numvalp
== NULL
) {
389 gettext("cannot read snapshot create time "
390 "kstat from kernel\n"));
395 printf("%-*s: ", MAX_LABEL_LEN
,
396 gettext("Snapshot create time"));
398 /* get the localized time */
399 tm
= localtime(&numvalp
->value
.l
);
400 if (strftime(buf
, sizeof (buf
),
402 /* Wouldn't fit in buf, fall back */
403 p
= ctime(&numvalp
->value
.l
);
408 * for script-readable options we want
409 * the locale-independent time only.
411 p
= ctime(&numvalp
->value
.l
);
413 /* p should already have a \n appended */
419 numvalp
= kstat_data_lookup(num
,
420 FSSNAP_KSTAT_NUM_CHUNKSIZE
);
421 if (numvalp
== NULL
) {
423 gettext("cannot read chunksize kstat\n"));
427 printf("%-*s: %lu KB\n", MAX_LABEL_LEN
,
428 gettext("Copy-on-write granularity"),
429 numvalp
->value
.ui32
/ 1024L);
431 printf("%lu\n", numvalp
->value
.ui32
);
436 * Print a place holder for unknown options so that
437 * the user can determine which option was not
438 * understood and the number outputted is the same
439 * number they requested.
445 printf(gettext("No such data type %d.\n"), order
[i
]);