diff --git a/utils/src/df.c b/utils/src/df.c new file mode 100644 index 00000000..86c1ae0f --- /dev/null +++ b/utils/src/df.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sparse.h" +#include "util.h" +#include "format.h" +#include "ioctl.h" +#include "cmd.h" + +#define COLS 8 + +static int df_cmd(int argc, char **argv) +{ + struct scoutfs_ioctl_alloc_detail ad; + struct scoutfs_ioctl_alloc_detail_entry *ade = NULL; + struct scoutfs_ioctl_statfs_more sfm; + char *title[COLS]; + u64 fields[COLS]; + int wid[COLS]; + u64 nr = 4096 / sizeof(*ade); + u64 meta_free = 0; + u64 data_free = 0; + int ret; + int fd; + int i; + + if (argc != 2) { + fprintf(stderr, "must specify path\n"); + return -EINVAL; + } + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "failed to open '%s': %s (%d)\n", + argv[1], strerror(errno), errno); + return ret; + } + + sfm.valid_bytes = sizeof(struct scoutfs_ioctl_statfs_more); + ret = ioctl(fd, SCOUTFS_IOC_STATFS_MORE, &sfm); + if (ret < 0) { + fprintf(stderr, "statfs_more returned %d: error %s (%d)\n", + ret, strerror(errno), errno); + ret = -EIO; + goto out; + } + + do { + free(ade); + ade = calloc(nr, sizeof(*ade)); + if (!ade) { + ret = -ENOMEM; + goto out; + } + + ad.entries_ptr = (intptr_t)ade; + ad.entries_nr = nr; + ret = ioctl(fd, SCOUTFS_IOC_ALLOC_DETAIL, &ad); + if (ret < 0 && errno == EOVERFLOW) + nr = nr + (nr >> 2); + } while (ret < 0 && errno == EOVERFLOW); + + if (ret < 0) { + fprintf(stderr, "alloc_detail returned %d: error %s (%d)\n", + ret, strerror(errno), errno); + ret = -EIO; + goto out; + } + + for (i = 0; i < ret; i++) { + if (ade[i].meta) + meta_free += ade[i].blocks; + else + data_free += ade[i].blocks; + } + + title[0] = "64K-Meta"; + title[1] = "Used"; + title[2] = "Avail"; + title[3] = "Use%"; + title[4] = "4K-Data"; + title[5] = "Used"; + title[6] = "Avail"; + title[7] = "Use%"; + + fields[0] = sfm.total_meta_blocks; + fields[1] = sfm.total_meta_blocks - meta_free; + fields[2] = meta_free; + fields[3] = fields[1] * 100 / fields[0]; + fields[4] = sfm.total_data_blocks; + fields[5] = sfm.total_data_blocks - data_free; + fields[6] = data_free; + fields[7] = fields[5] * 100 / fields[4]; + + for (i = 0; i < array_size(fields); i++) + wid[i] = max(snprintf(NULL, 0, "%s", title[i]), + snprintf(NULL, 0, "%llu", fields[i])); + + for (i = 0; i < array_size(fields); i++) + printf("%*s ", wid[i], title[i]); + printf("\n"); + for (i = 0; i < array_size(fields); i++) + wid[i] = printf("%*llu ", wid[i], fields[i]); + printf("\n"); + + ret = 0; +out: + free(ade); + return ret; +} + +static void __attribute__((constructor)) df_ctor(void) +{ + cmd_register("df", "", + "show metadata and data block usage", df_cmd); +} diff --git a/utils/src/format.h b/utils/src/format.h index 428c94e6..ee0e0d69 100644 --- a/utils/src/format.h +++ b/utils/src/format.h @@ -297,6 +297,12 @@ struct scoutfs_alloc_root { struct scoutfs_btree_root root; }__packed; +/* types of allocators, exposed to alloc_detail ioctl */ +#define SCOUTFS_ALLOC_OWNER_NONE 0 +#define SCOUTFS_ALLOC_OWNER_SERVER 1 +#define SCOUTFS_ALLOC_OWNER_MOUNT 2 +#define SCOUTFS_ALLOC_OWNER_SRCH 3 + struct scoutfs_mounted_client_btree_val { __u8 flags; } __packed; @@ -816,7 +822,6 @@ enum { SCOUTFS_NET_CMD_GET_ROOTS, SCOUTFS_NET_CMD_ADVANCE_SEQ, SCOUTFS_NET_CMD_GET_LAST_SEQ, - SCOUTFS_NET_CMD_STATFS, SCOUTFS_NET_CMD_LOCK, SCOUTFS_NET_CMD_LOCK_RECOVER, SCOUTFS_NET_CMD_SRCH_GET_COMPACT, @@ -857,13 +862,6 @@ struct scoutfs_net_inode_alloc { __le64 nr; } __packed; -struct scoutfs_net_statfs { - __le64 total_blocks; /* total blocks in device */ - __le64 next_ino; /* next unused inode number */ - __le64 bfree; /* free blocks */ - __u8 uuid[SCOUTFS_UUID_BYTES]; /* logical volume uuid */ -} __packed; - struct scoutfs_net_roots { struct scoutfs_btree_root fs_root; struct scoutfs_btree_root logs_root; diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index c953be45..f871d37e 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -394,4 +394,21 @@ struct scoutfs_ioctl_data_wait_err { #define SCOUTFS_IOC_DATA_WAIT_ERR _IOR(SCOUTFS_IOCTL_MAGIC, 11, \ struct scoutfs_ioctl_data_wait_err) + +#define SCOUTFS_IOC_ALLOC_DETAIL _IOR(SCOUTFS_IOCTL_MAGIC, 12, \ + struct scoutfs_ioctl_alloc_detail) + +struct scoutfs_ioctl_alloc_detail { + __u64 entries_ptr; + __u64 entries_nr; +}; + +struct scoutfs_ioctl_alloc_detail_entry { + __u64 id; + __u64 blocks; + __u8 type; + __u8 meta:1, + avail:1; +}; + #endif