#include "hammer.h"
#include <libutil.h>
#include <libhammer.h>
void show_info(char *path);
static double percent(int64_t value, int64_t total);
void
hammer_cmd_info(char **av, int ac)
{
struct statfs *stfsbuf;
int mntsize, i, first = 1;
char *fstype, *path;
tzset();
if (ac > 0) {
while (ac) {
show_info(*av);
--ac;
++av;
if (ac)
printf("\n");
}
} else {
mntsize = getmntinfo(&stfsbuf, MNT_NOWAIT);
if (mntsize > 0) {
for (i = 0; i < mntsize; i++) {
fstype = stfsbuf[i].f_fstypename;
path = stfsbuf[i].f_mntonname;
if ((strcmp(fstype, "hammer")) == 0) {
if (first)
first = 0;
else
printf("\n");
show_info(path);
}
}
if (first)
printf("No mounted HAMMER filesystems found\n");
} else {
printf("No mounted filesystems found\n");
}
}
}
static
void
__test_if_hammer_or_abort(const char *path)
{
struct hammer_ioc_info info;
int fd;
fd = open(path, O_RDONLY);
if (fd < 0) {
err(1, "Failed to open %s", path);
}
if (ioctl(fd, HAMMERIOC_GET_INFO, &info) < 0) {
err(1, "%s is probably not a HAMMER filesystem", path);
}
close(fd);
}
void
show_info(char *path)
{
libhammer_fsinfo_t fip;
libhammer_pfsinfo_t pi, pi_first;
struct hammer_ioc_volume_list ioc;
int64_t usedbigblocks;
int64_t usedbytes, rsvbytes;
int64_t totalbytes, freebytes;
char *fsid;
char buf[6];
char rootvol[MAXPATHLEN];
int i;
fsid = NULL;
usedbigblocks = 0;
usedbytes = totalbytes = rsvbytes = freebytes = 0;
__test_if_hammer_or_abort(path);
fip = libhammer_get_fsinfo(path);
if (fip == NULL) {
errx(1, "Failed to get filesystem info");
}
hammer_uuid_to_string(&fip->vol_fsid, &fsid);
if (hammer_fs_to_vol(path, &ioc) == -1) {
errx(1, "Failed to get volume paths");
}
if (hammer_fs_to_rootvol(path, rootvol, sizeof(rootvol)) == -1) {
errx(1, "Failed to get root volume path");
}
printf("Volume identification\n");
printf("\tLabel %s\n", fip->vol_name);
printf("\tNo. Volumes %d\n", fip->nvolumes);
printf("\tHAMMER Volumes ");
for (i = 0; i < ioc.nvols; i++) {
printf("%s", ioc.vols[i].device_name);
if (i != ioc.nvols - 1)
printf(":");
}
printf("\n");
printf("\tRoot Volume %s\n", rootvol);
printf("\tFSID %s\n", fsid);
printf("\tHAMMER Version %d\n", fip->version);
usedbigblocks = fip->bigblocks - fip->freebigblocks;
printf("Big-block information\n");
printf("\tTotal %10jd\n", (intmax_t)fip->bigblocks);
printf("\tUsed %10jd (%.2lf%%)\n"
"\tReserved %10jd (%.2lf%%)\n"
"\tFree %10jd (%.2lf%%)\n",
(intmax_t)usedbigblocks,
percent(usedbigblocks, fip->bigblocks),
(intmax_t)fip->rsvbigblocks,
percent(fip->rsvbigblocks, fip->bigblocks),
(intmax_t)(fip->freebigblocks - fip->rsvbigblocks),
percent(fip->freebigblocks - fip->rsvbigblocks, fip->bigblocks));
printf("Space information\n");
totalbytes = (fip->bigblocks << HAMMER_BIGBLOCK_BITS);
usedbytes = (usedbigblocks << HAMMER_BIGBLOCK_BITS);
rsvbytes = (fip->rsvbigblocks << HAMMER_BIGBLOCK_BITS);
freebytes = ((fip->freebigblocks - fip->rsvbigblocks)
<< HAMMER_BIGBLOCK_BITS);
printf("\tNo. Inodes %10jd\n", (intmax_t)fip->inodes);
humanize_number(buf, sizeof(buf) - (totalbytes < 0 ? 0 : 1),
totalbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
printf("\tTotal size %6s (%jd bytes)\n",
buf, (intmax_t)totalbytes);
humanize_number(buf, sizeof(buf) - (usedbytes < 0 ? 0 : 1),
usedbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
printf("\tUsed %6s (%.2lf%%)\n", buf,
percent(usedbytes, totalbytes));
humanize_number(buf, sizeof(buf) - (rsvbytes < 0 ? 0 : 1),
rsvbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
printf("\tReserved %6s (%.2lf%%)\n", buf,
percent(rsvbytes, totalbytes));
humanize_number(buf, sizeof(buf) - (freebytes < 0 ? 0 : 1),
freebytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
printf("\tFree %6s (%.2lf%%)\n", buf,
percent(freebytes, totalbytes));
printf("PFS information\n");
printf("\t PFS# Mode Snaps\n");
pi_first = libhammer_get_first_pfs(fip);
for (pi = pi_first; pi != NULL; pi = libhammer_get_next_pfs(pi)) {
printf("\t%6d %-6s",
pi->pfs_id, (pi->ismaster ? "MASTER" : "SLAVE"));
snprintf(buf, 6, "%d", pi->snapcount);
printf(" %6s", (pi->head.error && pi->snapcount == 0) ? "-" : buf);
if (pi->pfs_id == HAMMER_ROOT_PFSID)
printf(" (root PFS)");
printf("\n");
}
free(fsid);
libhammer_free_fsinfo(fip);
}
static
double
percent(int64_t value, int64_t total)
{
if (total == 0)
return 100.0;
return ((value * 100.0) / (double)total);
}