nvi - Work around problem with git
[dragonfly.git] / sbin / hammer / cmd_info.c
blob946d3c8a05bacadf41ddf15085026c53d00204e5
1 /*
2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Antonio Huete <tuxillo@quantumachine.net>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
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.
35 #include "hammer.h"
36 #include <libutil.h>
38 void show_info(char *path);
39 char *find_pfs_mount(int pfsid, uuid_t parentuuid, int ismaster);
40 double percent(int64_t value, int64_t total);
41 u_int32_t count_snapshots(int fd, u_int32_t version,
42 char *pfs_snapshots, char *mountedon);
44 void
45 hammer_cmd_info(void)
47 struct statfs *stfsbuf;
48 int mntsize, i, first = 1;
49 char *fstype, *path;
51 tzset();
52 mntsize = getmntinfo(&stfsbuf, MNT_NOWAIT);
53 if (mntsize > 0) {
54 for (i = 0; i < mntsize; i++) {
55 fstype = stfsbuf[i].f_fstypename;
56 path = stfsbuf[i].f_mntonname;
57 if ((strcmp(fstype, "hammer")) == 0) {
58 if (first)
59 first = 0;
60 else
61 fprintf(stdout, "\n");
62 show_info(path);
65 } else {
66 fprintf(stdout, "No mounted filesystems found\n");
71 void
72 show_info(char *path)
74 struct hammer_pseudofs_data pfs_od;
75 struct hammer_ioc_pseudofs_rw pfs;
76 int64_t usedbigblocks;
77 int64_t usedbytes, rsvbytes;
78 int64_t totalbytes, freebytes;
79 struct hammer_ioc_info info;
80 int fd, pfs_id, ismaster;
81 char *fsid;
82 char *mountedon;
83 char buf[6];
84 u_int32_t sc;
86 fsid = mountedon = NULL;
87 usedbigblocks = 0;
88 pfs_id = 0; /* Include PFS#0 */
89 usedbytes = totalbytes = rsvbytes = freebytes = 0;
90 sc = 0;
92 bzero(&info, sizeof(struct hammer_ioc_info));
94 /* Try to get a file descriptor based on the path given */
95 fd = open(path, O_RDONLY);
96 if (fd < 0) {
97 perror("show_info");
98 exit(EXIT_FAILURE);
101 if ((ioctl(fd, HAMMERIOC_GET_INFO, &info)) < 0) {
102 perror("show_info");
103 exit(EXIT_FAILURE);
106 /* Find out the UUID strings */
107 uuid_to_string(&info.vol_fsid, &fsid, NULL);
109 /* Volume information */
110 fprintf(stdout, "Volume identification\n");
111 fprintf(stdout, "\tLabel %s\n", info.vol_name);
112 fprintf(stdout, "\tNo. Volumes %d\n", info.nvolumes);
113 fprintf(stdout, "\tFSID %s\n", fsid);
114 fprintf(stdout, "\tHAMMER Version %d\n", info.version);
116 /* Big blocks information */
117 usedbigblocks = info.bigblocks - info.freebigblocks;
119 fprintf(stdout, "Big block information\n");
120 fprintf(stdout, "\tTotal %10jd\n", (intmax_t)info.bigblocks);
121 fprintf(stdout, "\tUsed %10jd (%.2lf%%)\n"
122 "\tReserved %10jd (%.2lf%%)\n"
123 "\tFree %10jd (%.2lf%%)\n",
124 (intmax_t)usedbigblocks,
125 percent(usedbigblocks, info.bigblocks),
126 (intmax_t)info.rsvbigblocks,
127 percent(info.rsvbigblocks, info.bigblocks),
128 (intmax_t)(info.freebigblocks - info.rsvbigblocks),
129 percent(info.freebigblocks - info.rsvbigblocks,
130 info.bigblocks));
131 fprintf(stdout, "Space information\n");
133 /* Space information */
134 totalbytes = (info.bigblocks << HAMMER_LARGEBLOCK_BITS);
135 usedbytes = (usedbigblocks << HAMMER_LARGEBLOCK_BITS);
136 rsvbytes = (info.rsvbigblocks << HAMMER_LARGEBLOCK_BITS);
137 freebytes = ((info.freebigblocks - info.rsvbigblocks)
138 << HAMMER_LARGEBLOCK_BITS);
140 fprintf(stdout, "\tNo. Inodes %10jd\n", (intmax_t)info.inodes);
141 humanize_number(buf, sizeof(buf) - (totalbytes < 0 ? 0 : 1),
142 totalbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
143 fprintf(stdout, "\tTotal size %6s (%jd bytes)\n",
144 buf, (intmax_t)totalbytes);
146 humanize_number(buf, sizeof(buf) - (usedbytes < 0 ? 0 : 1),
147 usedbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
148 fprintf(stdout, "\tUsed %6s (%.2lf%%)\n", buf,
149 percent(usedbytes, totalbytes));
151 humanize_number(buf, sizeof(buf) - (rsvbytes < 0 ? 0 : 1),
152 rsvbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
153 fprintf(stdout, "\tReserved %6s (%.2lf%%)\n", buf,
154 percent(rsvbytes, totalbytes));
156 humanize_number(buf, sizeof(buf) - (freebytes < 0 ? 0 : 1),
157 freebytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
158 fprintf(stdout, "\tFree %6s (%.2lf%%)\n", buf,
159 percent(freebytes, totalbytes));
161 /* Pseudo-filesystem information */
162 fprintf(stdout, "PFS information\n");
163 fprintf(stdout, "\tPFS ID Mode Snaps Mounted on\n");
165 while(pfs_id < HAMMER_MAX_PFS) {
166 bzero(&pfs, sizeof(pfs));
167 bzero(&pfs_od, sizeof(pfs_od));
168 pfs.pfs_id = pfs_id;
169 pfs.ondisk = &pfs_od;
170 pfs.bytes = sizeof(pfs_od);
171 pfs.version = HAMMER_IOC_PSEUDOFS_VERSION;
172 if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) >= 0) {
173 ismaster = (pfs_od.mirror_flags & HAMMER_PFSD_SLAVE)
174 ? 0 : 1;
175 if (pfs_id == 0)
176 mountedon = strdup(path);
177 else
178 mountedon = find_pfs_mount(pfs_id,
179 info.vol_fsid, ismaster);
181 sc = count_snapshots(fd, info.version, pfs_od.snapshots,
182 mountedon);
184 fprintf(stdout, "\t%6d %-6s %6d ",
185 pfs_id, (ismaster ? "MASTER" : "SLAVE"), sc);
186 if (mountedon)
187 fprintf(stdout, "%s", mountedon);
188 else
189 fprintf(stdout, "not mounted");
190 fprintf(stdout, "\n");
192 pfs_id++;
195 free(fsid);
196 free(mountedon);
199 char *
200 find_pfs_mount(int pfsid, uuid_t parentuuid, int ismaster)
202 struct hammer_ioc_info hi;
203 struct statfs *mntbuf;
204 int mntsize;
205 int curmount;
206 int fd;
207 size_t mntbufsize;
208 char *trailstr;
209 char *retval;
211 retval = NULL;
213 /* Do not continue if there are no mounted filesystems */
214 mntsize = getfsstat(NULL, 0, MNT_NOWAIT);
215 if (mntsize <= 0)
216 return retval;
218 mntbufsize = (mntsize) * sizeof(struct statfs);
219 mntbuf = malloc(mntbufsize);
220 if (mntbuf == NULL) {
221 perror("show_info");
222 exit(EXIT_FAILURE);
225 mntsize = getfsstat(mntbuf, (long)mntbufsize, MNT_NOWAIT);
226 curmount = mntsize - 1;
228 asprintf(&trailstr, ":%05d", pfsid);
231 * Iterate all the mounted points looking for the PFS passed to
232 * this function.
234 while(curmount >= 0) {
236 * We need to avoid that PFS belonging to other HAMMER
237 * filesystems are showed as mounted, so we compare
238 * against the FSID, which is presumable to be unique.
240 bzero(&hi, sizeof(hi));
241 if ((fd = open(mntbuf[curmount].f_mntfromname, O_RDONLY)) < 0) {
242 curmount--;
243 continue;
246 if ((ioctl(fd, HAMMERIOC_GET_INFO, &hi)) < 0) {
247 curmount--;
248 continue;
251 if (strstr(mntbuf[curmount].f_mntfromname, trailstr) != NULL &&
252 (uuid_compare(&hi.vol_fsid, &parentuuid, NULL)) == 0) {
253 if (ismaster) {
254 if (strstr(mntbuf[curmount].f_mntfromname,
255 "@@-1") != NULL) {
256 retval =
257 strdup(mntbuf[curmount].f_mntonname);
258 break;
260 } else {
261 if (strstr(mntbuf[curmount].f_mntfromname,
262 "@@0x") != NULL ) {
263 retval =
264 strdup(mntbuf[curmount].f_mntonname);
265 break;
269 curmount--;
271 free(trailstr);
272 return retval;
275 double
276 percent(int64_t value, int64_t total)
278 /* Avoid divide-by-zero */
279 if (total == 0)
280 return 100.0;
282 return ((value * 100.0) / (double)total);
285 u_int32_t
286 count_snapshots(int fd, u_int32_t version, char *pfs_snapshots, char *mountedon)
288 struct hammer_ioc_snapshot snapinfo;
289 char *snapshots_path, *fpath;
290 struct dirent *den;
291 struct stat st;
292 DIR *dir;
293 u_int32_t snapshot_count = 0;
295 bzero(&snapinfo, sizeof(struct hammer_ioc_snapshot));
296 if (version < 3) {
298 * old style: count the number of softlinks in the snapshots dir
300 if (pfs_snapshots[0])
301 snapshots_path = pfs_snapshots;
302 else
303 asprintf(&snapshots_path, "%s/snapshots", mountedon);
304 if ((dir = opendir(snapshots_path)) != NULL) {
305 while ((den = readdir(dir)) != NULL) {
306 if (den->d_name[0] == '.')
307 continue;
308 asprintf(&fpath, "%s/%s", snapshots_path,
309 den->d_name);
310 if (lstat(fpath, &st) == 0 &&
311 S_ISLNK(st.st_mode))
312 snapshot_count++;
313 free(fpath);
315 closedir(dir);
317 } else {
319 * new style: file system meta-data
321 do {
322 if (ioctl(fd, HAMMERIOC_GET_SNAPSHOT, &snapinfo) < 0) {
323 perror("count_snapshots");
324 exit(EXIT_FAILURE);
326 snapshot_count += snapinfo.count;
327 } while (snapinfo.head.error == 0 && snapinfo.count);
329 return snapshot_count;