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.
37 #include <sys/fssnap_if.h>
41 static void fssnap_display_info(ulong_t
, int *, int);
43 #define MAX_INFO_DESCRIPTORS (10)
45 static char *infosubopts
[] = {
46 #define INFO_SNAPSHOT (0)
48 #define INFO_BLKDEV (1)
50 #define INFO_CHARDEV (2)
52 #define INFO_MNTPT (3)
54 #define INFO_STATE (4)
56 #define INFO_BACKPATH (5)
58 #define INFO_BACKSIZE (6)
60 #define INFO_MAXSIZE (7)
62 #define INFO_CREATETIME (8)
64 #define INFO_CHUNKSIZE (9)
69 #define BLOCK_PATH "/dev/" SNAP_BLOCK_NAME "/"
70 #define CHAR_PATH "/dev/" SNAP_CHAR_NAME "/"
72 /* labels are truncated to this many characters when displayed */
73 #define MAX_LABEL_LEN (30)
76 * fssnap_show_status() - display file system snapshot status
78 * displays snapshot information. If mountpoint is set, information is
79 * only displayed for the snapshot (if one exists) on that file system.
80 * If mountpoint is NULL, information is displayed for all snapshots.
82 * If opts is defined, it is parsed as a list of suboptions (via
83 * getsubopt()) corresponding to the options list defined above. These
84 * options determine what data should be displayed and in what order. An
85 * option may appear more than once.
87 * The labels parameter is a boolean that determines whether labels
88 * (internationalized) are displayed before each data element. If it is
89 * 0, labels are not displayed, otherwise they are. The labels parameter
90 * is ignored if brief is nonzero.
92 * The brief parameter is also a boolean and specifies a mode where only
93 * the snapshot number and mount point are displayed, regardless of the
94 * value of labels. This could be used for listing all active snapshots.
96 * Based on these parameters, an order list is created that tells
97 * fssnap_display_info() what info to display and in what order.
99 * Note that when labels are not specified, the assumption is that the
100 * output is made for script readable consumption. For this reason, text
101 * is not I18N'd and numbers are left as bytes instead of converted to KB.
104 fssnap_show_status(char *mountpoint
, char *opts
, int labels
, int brief
)
106 int *order
, orderlen
= MAX_INFO_DESCRIPTORS
+1;
110 kstat_named_t
*highp
;
111 char *suboptions
, *v
, *n
;
115 kslib
= kstat_open();
116 kshigh
= kstat_lookup(kslib
, SNAP_NAME
, 0, FSSNAP_KSTAT_HIGHWATER
);
119 * First check and see if they gave us a mount point or a device
120 * name (ie /dev/fssnap/X or /dev/rfssnap/X).
123 if (strncmp(BLOCK_PATH
, mountpoint
, strlen(BLOCK_PATH
)) == 0 ||
124 strncmp(CHAR_PATH
, mountpoint
, strlen(CHAR_PATH
)) == 0) {
125 n
= strrchr(mountpoint
, '/');
129 num
= (int)strtol(n
, NULL
, 10);
139 order
= (int *)malloc(orderlen
* sizeof (int));
142 gettext("cannot allocate order list.\n"));
146 while (*suboptions
!= '\0') {
148 * -1 means invalid option, MAX_INFO_DESCRIPTORS is
151 order
[i
++] = getsubopt(&suboptions
, infosubopts
, &v
);
153 order
= (int *)realloc(order
,
154 sizeof (int) * (orderlen
*= 2));
157 gettext("cannot reallocate order "
164 order
[i
] = MAX_INFO_DESCRIPTORS
;
166 order
= (int *)malloc(orderlen
* sizeof (int));
169 gettext("cannot allocate order list.\n"));
172 for (i
= 0; i
<= MAX_INFO_DESCRIPTORS
; i
++)
176 /* check if fssnap module is loaded */
177 if (kshigh
== NULL
) {
182 (void) kstat_read(kslib
, kshigh
, NULL
);
183 highp
= kstat_data_lookup(kshigh
, FSSNAP_KSTAT_HIGHWATER
);
185 /* Loop up to the maximum number of snapshots */
186 for (i
= 0; i
<= highp
->value
.ui32
; i
++) {
187 mnt
= kstat_lookup(kslib
, SNAP_NAME
, i
, FSSNAP_KSTAT_MNTPT
);
189 /* if this snapshot is not allocated, skip to the next */
192 if (kstat_read(kslib
, mnt
, NULL
) == -1)
194 if (mountpoint
!= NULL
) {
195 if ((usenum
&& i
!= num
) ||
196 (!usenum
&& strcmp(mountpoint
, mnt
->ks_data
) != 0))
201 printf("%4d\t%s\n", i
, (char *)mnt
->ks_data
);
203 fssnap_display_info(i
, order
, labels
);
208 fssnap_display_info(ulong_t snapnum
, int *order
, int labels
)
212 kstat_named_t
*numvalp
;
214 u_longlong_t inuse
, size
= 0;
215 char buf
[BUFSIZ
], *first
;
219 kslib
= kstat_open();
220 num
= kstat_lookup(kslib
, SNAP_NAME
, snapnum
, FSSNAP_KSTAT_NUM
);
224 if (kstat_read(kslib
, num
, NULL
) == -1)
227 for (i
= 0; order
[i
] != MAX_INFO_DESCRIPTORS
; i
++) {
231 printf("%-*s: %lu\n", MAX_LABEL_LEN
,
232 gettext("Snapshot number"), snapnum
);
234 printf("%lu\n", snapnum
);
238 printf("%-*s: /dev/%s/%lu\n", MAX_LABEL_LEN
,
239 gettext("Block Device"), SNAP_BLOCK_NAME
,
242 printf("/dev/%s/%lu\n", SNAP_BLOCK_NAME
,
247 printf("%-*s: /dev/%s/%lu\n", MAX_LABEL_LEN
,
248 gettext("Raw Device"), SNAP_CHAR_NAME
,
251 printf("/dev/%s/%lu\n", SNAP_CHAR_NAME
,
256 mnt
= kstat_lookup(kslib
, SNAP_NAME
, snapnum
,
260 gettext("cannot read mount point kstat\n"));
263 if (kstat_read(kslib
, mnt
, NULL
) == -1) {
267 printf("%-*s: %s\n", MAX_LABEL_LEN
,
268 gettext("Mount point"),
269 (char *)mnt
->ks_data
);
271 printf("%s\n", (char *)mnt
->ks_data
);
275 numvalp
= kstat_data_lookup(num
,
276 FSSNAP_KSTAT_NUM_STATE
);
277 if (numvalp
== NULL
) {
279 gettext("cannot read state kstat\n"));
284 printf("%-*s: ", MAX_LABEL_LEN
,
285 gettext("Device state"));
286 switch (numvalp
->value
.i32
) {
287 case 0: printf(gettext("creating\n"));
289 case 1: printf(gettext("idle\n"));
291 case 2: printf(gettext("active\n"));
293 case 3: printf(gettext("disabled\n"));
295 default: printf(gettext("unknown\n"));
299 switch (numvalp
->value
.i32
) {
300 case 0: printf("creating\n");
302 case 1: printf("idle\n");
304 case 2: printf("active\n");
306 case 3: printf("disabled\n");
308 default: printf("unknown\n");
315 /* backing file kstat */
316 back
= kstat_lookup(kslib
, SNAP_NAME
, snapnum
,
317 FSSNAP_KSTAT_BFNAME
);
319 (kstat_read(kslib
, back
, NULL
) == -1) ||
320 (back
->ks_data
== NULL
)) {
322 gettext("cannot read backing file name "
323 "kstat from kernel\n"));
327 printf("%-*s: %s\n", MAX_LABEL_LEN
,
328 gettext("Backing store path"),
329 (char *)back
->ks_data
);
331 printf("%s\n", (char *)back
->ks_data
);
335 numvalp
= kstat_data_lookup(num
,
336 FSSNAP_KSTAT_NUM_BFSIZE
);
337 if (numvalp
== NULL
) {
339 gettext("cannot read backing file size "
340 "kstat from kernel\n"));
344 size
= numvalp
->value
.ui64
;
347 printf("%-*s: %llu KB\n", MAX_LABEL_LEN
,
348 gettext("Backing store size"),
351 printf("%llu\n", size
);
355 numvalp
= kstat_data_lookup(num
,
356 FSSNAP_KSTAT_NUM_MAXSIZE
);
357 if (numvalp
== NULL
) {
359 gettext("cannot read backing file maxsize "
360 "kstat from kernel\n"));
364 printf("%-*s: ", MAX_LABEL_LEN
,
365 gettext("Maximum backing store size"));
367 if (numvalp
->value
.ui64
== 0LL)
368 printf(gettext("Unlimited\n"));
371 numvalp
->value
.ui64
/ 1024LL);
373 printf("%llu\n", numvalp
->value
.ui64
);
377 case INFO_CREATETIME
:
379 /* snapshot creation time */
384 numvalp
= kstat_data_lookup(num
,
385 FSSNAP_KSTAT_NUM_CREATETIME
);
386 if (numvalp
== NULL
) {
388 gettext("cannot read snapshot create time "
389 "kstat from kernel\n"));
394 printf("%-*s: ", MAX_LABEL_LEN
,
395 gettext("Snapshot create time"));
397 /* get the localized time */
398 tm
= localtime(&numvalp
->value
.l
);
399 if (strftime(buf
, sizeof (buf
),
401 /* Wouldn't fit in buf, fall back */
402 p
= ctime(&numvalp
->value
.l
);
407 * for script-readable options we want
408 * the locale-independent time only.
410 p
= ctime(&numvalp
->value
.l
);
412 /* p should already have a \n appended */
418 numvalp
= kstat_data_lookup(num
,
419 FSSNAP_KSTAT_NUM_CHUNKSIZE
);
420 if (numvalp
== NULL
) {
422 gettext("cannot read chunksize kstat\n"));
426 printf("%-*s: %lu KB\n", MAX_LABEL_LEN
,
427 gettext("Copy-on-write granularity"),
428 numvalp
->value
.ui32
/ 1024L);
430 printf("%lu\n", numvalp
->value
.ui32
);
435 * Print a place holder for unknown options so that
436 * the user can determine which option was not
437 * understood and the number outputted is the same
438 * number they requested.
444 printf(gettext("No such data type %d.\n"), order
[i
]);