mirror of
https://github.com/versity/scoutfs.git
synced 2026-09-07 00:26:59 +00:00
scoutfs-utils: add fd which uses alloc_detail
Add the df command which uses the new alloc_detail ioctl to show df for the metadata and data devices separately. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
+126
@@ -0,0 +1,126 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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", "<path>",
|
||||
"show metadata and data block usage", df_cmd);
|
||||
}
|
||||
+6
-8
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user