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
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
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
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
);
47 struct statfs
*stfsbuf
;
48 int mntsize
, i
, first
= 1;
52 mntsize
= getmntinfo(&stfsbuf
, MNT_NOWAIT
);
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) {
61 fprintf(stdout
, "\n");
66 fprintf(stdout
, "No mounted filesystems found\n");
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
;
86 fsid
= mountedon
= NULL
;
88 pfs_id
= 0; /* Include PFS#0 */
89 usedbytes
= totalbytes
= rsvbytes
= freebytes
= 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
);
101 if ((ioctl(fd
, HAMMERIOC_GET_INFO
, &info
)) < 0) {
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
,
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
));
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
)
176 mountedon
= strdup(path
);
178 mountedon
= find_pfs_mount(pfs_id
,
179 info
.vol_fsid
, ismaster
);
181 sc
= count_snapshots(fd
, info
.version
, pfs_od
.snapshots
,
184 fprintf(stdout
, "\t%6d %-6s %6d ",
185 pfs_id
, (ismaster
? "MASTER" : "SLAVE"), sc
);
187 fprintf(stdout
, "%s", mountedon
);
189 fprintf(stdout
, "not mounted");
190 fprintf(stdout
, "\n");
200 find_pfs_mount(int pfsid
, uuid_t parentuuid
, int ismaster
)
202 struct hammer_ioc_info hi
;
203 struct statfs
*mntbuf
;
213 /* Do not continue if there are no mounted filesystems */
214 mntsize
= getfsstat(NULL
, 0, MNT_NOWAIT
);
218 mntbufsize
= (mntsize
) * sizeof(struct statfs
);
219 mntbuf
= malloc(mntbufsize
);
220 if (mntbuf
== NULL
) {
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
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) {
246 if ((ioctl(fd
, HAMMERIOC_GET_INFO
, &hi
)) < 0) {
251 if (strstr(mntbuf
[curmount
].f_mntfromname
, trailstr
) != NULL
&&
252 (uuid_compare(&hi
.vol_fsid
, &parentuuid
, NULL
)) == 0) {
254 if (strstr(mntbuf
[curmount
].f_mntfromname
,
257 strdup(mntbuf
[curmount
].f_mntonname
);
261 if (strstr(mntbuf
[curmount
].f_mntfromname
,
264 strdup(mntbuf
[curmount
].f_mntonname
);
276 percent(int64_t value
, int64_t total
)
278 /* Avoid divide-by-zero */
282 return ((value
* 100.0) / (double)total
);
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
;
293 u_int32_t snapshot_count
= 0;
295 bzero(&snapinfo
, sizeof(struct hammer_ioc_snapshot
));
298 * old style: count the number of softlinks in the snapshots dir
300 if (pfs_snapshots
[0])
301 snapshots_path
= pfs_snapshots
;
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] == '.')
308 asprintf(&fpath
, "%s/%s", snapshots_path
,
310 if (lstat(fpath
, &st
) == 0 &&
319 * new style: file system meta-data
322 if (ioctl(fd
, HAMMERIOC_GET_SNAPSHOT
, &snapinfo
) < 0) {
323 perror("count_snapshots");
326 snapshot_count
+= snapinfo
.count
;
327 } while (snapinfo
.head
.error
== 0 && snapinfo
.count
);
329 return snapshot_count
;