xref: /dragonfly/sbin/hammer/cmd_info.c (revision fef7d5c7)
1 /*
2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Antonio Huete <tuxillo@quantumachine.net>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35 
36 #include "hammer.h"
37 
38 #include <libutil.h>
39 #include <libhammer.h>
40 
41 void show_info(char *path);
42 static double percent(int64_t value, int64_t total);
43 
44 void
45 hammer_cmd_info(char **av, int ac)
46 {
47 	struct statfs *stfsbuf;
48 	int mntsize, i, first = 1;
49 	char *fstype, *path;
50 
51 	tzset();
52 
53 	if (ac > 0) {
54                 while (ac) {
55                         show_info(*av);
56                         --ac;
57                         ++av;
58 			if (ac)
59 				printf("\n");
60                 }
61 	} else {
62 		mntsize = getmntinfo(&stfsbuf, MNT_NOWAIT);
63 		if (mntsize > 0) {
64 			for (i = 0; i < mntsize; i++) {
65 				fstype = stfsbuf[i].f_fstypename;
66 				path = stfsbuf[i].f_mntonname;
67 				if ((strcmp(fstype, "hammer")) == 0) {
68 					if (first)
69 						first = 0;
70 					else
71 						printf("\n");
72 					show_info(path);
73 				}
74 			}
75 			if (first)
76 				printf("No mounted HAMMER filesystems found\n");
77 		} else {
78 			printf("No mounted filesystems found\n");
79 		}
80 	}
81 }
82 
83 /*
84  * This is an adhoc function which exists only because libhammer can't
85  * properly handle variety of errors.
86  */
87 static
88 void
89 __test_if_hammer_or_abort(const char *path)
90 {
91 	struct hammer_ioc_info info;
92 	int fd;
93 
94 	fd = open(path, O_RDONLY);
95 	if (fd < 0) {
96 		err(1, "Failed to open %s", path);
97 		/* not reached */
98 	}
99 
100 	/*
101 	 * This ioctl never fails as long as fd is for HAMMER filesystem,
102 	 * thus we can assume path isn't in HAMMER if this fails.
103 	 */
104 	if (ioctl(fd, HAMMERIOC_GET_INFO, &info) < 0) {
105 		err(1, "%s is probably not a HAMMER filesystem", path);
106 		/* not reached */
107 	}
108 
109 	close(fd);
110 }
111 
112 void
113 show_info(char *path)
114 {
115 	libhammer_fsinfo_t fip;
116 	libhammer_pfsinfo_t pi, pi_first;
117 	struct hammer_ioc_volume_list ioc;
118 	int64_t	    usedbigblocks;
119 	int64_t	    usedbytes, rsvbytes;
120 	int64_t	    totalbytes, freebytes;
121 	char	    *fsid;
122 	char	    buf[6];
123 	char	    rootvol[MAXPATHLEN];
124 	int i;
125 
126 	fsid = NULL;
127 	usedbigblocks = 0;
128 
129 	usedbytes = totalbytes = rsvbytes = freebytes = 0;
130 
131 	/* Need to do this before libhammer gets involved */
132 	__test_if_hammer_or_abort(path);
133 
134 	fip = libhammer_get_fsinfo(path);
135 	if (fip == NULL) {
136 		errx(1, "Failed to get filesystem info");
137 		/* not reached */
138 	}
139 
140 	/* Find out the UUID strings */
141 	hammer_uuid_to_string(&fip->vol_fsid, &fsid);
142 
143 	/* Get the volume paths */
144 	if (hammer_fs_to_vol(path, &ioc) == -1) {
145 		errx(1, "Failed to get volume paths");
146 		/* not reached */
147 	}
148 
149 	/* Get the root volume path */
150 	if (hammer_fs_to_rootvol(path, rootvol, sizeof(rootvol)) == -1) {
151 		errx(1, "Failed to get root volume path");
152 		/* not reached */
153 	}
154 
155 	/* Volume information */
156 	printf("Volume identification\n");
157 	printf("\tLabel               %s\n", fip->vol_name);
158 	printf("\tNo. Volumes         %d\n", fip->nvolumes);
159 	printf("\tHAMMER Volumes      ");
160 	for (i = 0; i < ioc.nvols; i++) {
161 		printf("%s", ioc.vols[i].device_name);
162 		if (i != ioc.nvols - 1)
163 			printf(":");
164 	}
165 	printf("\n");
166 	printf("\tRoot Volume         %s\n", rootvol);
167 	printf("\tFSID                %s\n", fsid);
168 	printf("\tHAMMER Version      %d\n", fip->version);
169 
170 	/* Big-blocks information */
171 	usedbigblocks = fip->bigblocks - fip->freebigblocks;
172 
173 	printf("Big-block information\n");
174 	printf("\tTotal      %10jd\n", (intmax_t)fip->bigblocks);
175 	printf("\tUsed       %10jd (%.2lf%%)\n"
176 	       "\tReserved   %10jd (%.2lf%%)\n"
177 	       "\tFree       %10jd (%.2lf%%)\n",
178 		(intmax_t)usedbigblocks,
179 		percent(usedbigblocks, fip->bigblocks),
180 		(intmax_t)fip->rsvbigblocks,
181 		percent(fip->rsvbigblocks, fip->bigblocks),
182 		(intmax_t)(fip->freebigblocks - fip->rsvbigblocks),
183 		percent(fip->freebigblocks - fip->rsvbigblocks, fip->bigblocks));
184 	printf("Space information\n");
185 
186 	/* Space information */
187 	totalbytes = (fip->bigblocks << HAMMER_BIGBLOCK_BITS);
188 	usedbytes = (usedbigblocks << HAMMER_BIGBLOCK_BITS);
189 	rsvbytes = (fip->rsvbigblocks << HAMMER_BIGBLOCK_BITS);
190 	freebytes = ((fip->freebigblocks - fip->rsvbigblocks)
191 	    << HAMMER_BIGBLOCK_BITS);
192 
193 	printf("\tNo. Inodes %10jd\n", (intmax_t)fip->inodes);
194 	humanize_number(buf, sizeof(buf)  - (totalbytes < 0 ? 0 : 1),
195 	    totalbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
196 	printf("\tTotal size     %6s (%jd bytes)\n",
197 	    buf, (intmax_t)totalbytes);
198 
199 	humanize_number(buf, sizeof(buf)  - (usedbytes < 0 ? 0 : 1),
200 	    usedbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
201 	printf("\tUsed           %6s (%.2lf%%)\n", buf,
202 	    percent(usedbytes, totalbytes));
203 
204 	humanize_number(buf, sizeof(buf)  - (rsvbytes < 0 ? 0 : 1),
205 	    rsvbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
206 	printf("\tReserved       %6s (%.2lf%%)\n", buf,
207 	    percent(rsvbytes, totalbytes));
208 
209 	humanize_number(buf, sizeof(buf)  - (freebytes < 0 ? 0 : 1),
210 	    freebytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
211 	printf("\tFree           %6s (%.2lf%%)\n", buf,
212 	    percent(freebytes, totalbytes));
213 
214 	/* Pseudo-filesystem information */
215 	printf("PFS information\n");
216 	printf("\t  PFS#  Mode    Snaps\n");
217 
218 	/* Iterate all the PFSs found */
219 	pi_first = libhammer_get_first_pfs(fip);
220 	for (pi = pi_first; pi != NULL; pi = libhammer_get_next_pfs(pi)) {
221 		printf("\t%6d  %-6s",
222 		    pi->pfs_id, (pi->ismaster ? "MASTER" : "SLAVE"));
223 
224 		snprintf(buf, 6, "%d", pi->snapcount);
225 		printf(" %6s", (pi->head.error && pi->snapcount == 0) ? "-" : buf);
226 		if (pi->pfs_id == HAMMER_ROOT_PFSID)
227 			printf(" (root PFS)");
228 		printf("\n");
229 	}
230 
231 	free(fsid);
232 
233 	libhammer_free_fsinfo(fip);
234 
235 }
236 
237 static
238 double
239 percent(int64_t value, int64_t total)
240 {
241 	/* Avoid divide-by-zero */
242 	if (total == 0)
243 		return 100.0;
244 
245 	return ((value * 100.0) / (double)total);
246 }
247