From 70efa2f9059cfa440448907c2a52194ad7f0df93 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 19 Jul 2019 16:34:37 -0700 Subject: [PATCH] scoutfs-utils: add statfs wrapper Add a scoutfs command wrapper around the statfs_moe ioctl. It's the same as the stat_more ioctl but has different fields and a different ioctl. Signed-off-by: Zach Brown --- utils/src/ioctl.h | 22 +++++++ utils/src/stat.c | 144 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 136 insertions(+), 30 deletions(-) diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index 5aa057c0..5693668e 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -347,4 +347,26 @@ struct scoutfs_ioctl_find_xattrs { #define SCOUTFS_IOC_FIND_XATTRS _IOR(SCOUTFS_IOCTL_MAGIC, 10, \ struct scoutfs_ioctl_find_xattrs) +/* + * Give the user information about the filesystem. + * + * @valid_bytes stores the number of bytes that are valid in the + * structure. The caller sets this to the size of the struct that they + * understand. The kernel then fills and copies back the min of the + * size they and the user caller understand. The user can tell if a + * field is set if all of its bytes are within the valid_bytes that the + * kernel set on return. + * + * New fields are only added to the end of the struct. + */ +struct scoutfs_ioctl_statfs_more { + __u64 valid_bytes; + __u64 fsid; + __u64 rid; +} __packed; + +#define SCOUTFS_IOC_STATFS_MORE _IOR(SCOUTFS_IOCTL_MAGIC, 11, \ + struct scoutfs_ioctl_statfs_more) + + #endif diff --git a/utils/src/stat.c b/utils/src/stat.c index 2ae1a91e..9187feb2 100644 --- a/utils/src/stat.c +++ b/utils/src/stat.c @@ -16,43 +16,115 @@ #include "ioctl.h" #include "cmd.h" -#define FIELD(f) { \ - .name = #f, \ - .offset = offsetof(struct scoutfs_ioctl_stat_more, f), \ -} - -static struct stat_more_field { +struct stat_more_field { char *name; size_t offset; -} fields[] = { - FIELD(meta_seq), - FIELD(data_seq), - FIELD(data_version), - FIELD(online_blocks), - FIELD(offline_blocks), +}; + +#define FIELD(f, o) { \ + .name = #f, \ + .offset = o, \ +} + +#define INODE_FIELD_OFF(f) offsetof(struct scoutfs_ioctl_stat_more, f) +#define INODE_FIELD(f) FIELD(f, INODE_FIELD_OFF(f)) + +static struct stat_more_field inode_fields[] = { + INODE_FIELD(meta_seq), + INODE_FIELD(data_seq), + INODE_FIELD(data_version), + INODE_FIELD(online_blocks), + INODE_FIELD(offline_blocks), { NULL, } }; -#define for_each_field(f) \ +static void print_inode_field(void *st, size_t off) +{ + struct scoutfs_ioctl_stat_more *stm = st; + + switch(off) { + case INODE_FIELD_OFF(meta_seq): + printf("%llu", stm->meta_seq); + break; + case INODE_FIELD_OFF(data_seq): + printf("%llu", stm->data_seq); + break; + case INODE_FIELD_OFF(data_version): + printf("%llu", stm->data_version); + break; + case INODE_FIELD_OFF(online_blocks): + printf("%llu", stm->online_blocks); + break; + case INODE_FIELD_OFF(offline_blocks): + printf("%llu", stm->offline_blocks); + break; + }; +} + +#define FS_FIELD_OFF(f) offsetof(struct scoutfs_ioctl_statfs_more, f) +#define FS_FIELD(f) FIELD(f, FS_FIELD_OFF(f)) + +static struct stat_more_field fs_fields[] = { + FS_FIELD(fsid), + FS_FIELD(rid), + { NULL, } +}; + +static void print_fs_field(void *st, size_t off) +{ + struct scoutfs_ioctl_statfs_more *sfm = st; + + switch(off) { + case FS_FIELD_OFF(fsid): + printf("%016llx", sfm->fsid); + break; + case FS_FIELD_OFF(rid): + printf("%016llx", sfm->rid); + break; + }; +} + +#define for_each_field(f, fields) \ for (f = fields; f->name; f++) +typedef void (*print_field_t)(void *st, size_t off); + static struct option long_ops[] = { { "single_field", 1, NULL, 's' }, { NULL, 0, NULL, 0} }; -static int stat_more_cmd(int argc, char **argv) +static int do_stat(int argc, char **argv, int is_inode) { - struct scoutfs_ioctl_stat_more stm; + union { + struct scoutfs_ioctl_stat_more stm; + struct scoutfs_ioctl_statfs_more sfm; + } st; struct stat_more_field *single = NULL; + struct stat_more_field *fields; struct stat_more_field *fi; char *single_name = NULL; + print_field_t pr = NULL; char *path; + int cmd; int ret; int fd; int i; int c; + memset(&st, 0, sizeof(st)); + if (is_inode) { + cmd = SCOUTFS_IOC_STAT_MORE; + fields = inode_fields; + st.stm.valid_bytes = sizeof(struct scoutfs_ioctl_stat_more); + pr = print_inode_field; + } else { + cmd = SCOUTFS_IOC_STATFS_MORE; + fields = fs_fields; + st.sfm.valid_bytes = sizeof(struct scoutfs_ioctl_statfs_more); + pr = print_fs_field; + } + while ((c = getopt_long(argc, argv, "s:", long_ops, NULL)) != -1) { switch (c) { case 's': @@ -66,15 +138,14 @@ static int stat_more_cmd(int argc, char **argv) } if (single_name) { - for_each_field(fi) { + for_each_field(fi, fields) { if (strcmp(fi->name, single_name) == 0) { single = fi; break; } } if (!single) { - fprintf(stderr, "unknown stat_more field: '%s'\n", - single_name); + fprintf(stderr, "unknown field: '%s'\n", single_name); return -EINVAL; } } @@ -95,24 +166,21 @@ static int stat_more_cmd(int argc, char **argv) continue; } - memset(&stm, 0, sizeof(stm)); - stm.valid_bytes = sizeof(stm); - - ret = ioctl(fd, SCOUTFS_IOC_STAT_MORE, &stm); + ret = ioctl(fd, cmd, &st); if (ret < 0) { ret = -errno; - fprintf(stderr, "stat_more ioctl failed on '%s': " + fprintf(stderr, "ioctl failed on '%s': " "%s (%d)\n", path, strerror(errno), errno); } else if (single) { - printf("%llu\n", - *(u64 *)((void *)&stm + single->offset)); - + pr(&st, single->offset); + printf("\n"); } else { printf("%-17s %s\n", "path", path); - for_each_field(fi) { - printf("%-17s %llu\n", fi->name, - *(u64 *)((void *)&stm + fi->offset)); + for_each_field(fi, fields) { + printf("%-17s ", fi->name); + pr(&st, fi->offset); + printf("\n"); } } @@ -122,8 +190,24 @@ static int stat_more_cmd(int argc, char **argv) return 0; } +static int stat_more_cmd(int argc, char **argv) +{ + return do_stat(argc, argv, 1); +} + +static int statfs_more_cmd(int argc, char **argv) +{ + return do_stat(argc, argv, 0); +} + static void __attribute__((constructor)) stat_more_ctor(void) { cmd_register("stat", "", - "print scoutfs stat information for path", stat_more_cmd); + "show scoutfs inode information", stat_more_cmd); +} + +static void __attribute__((constructor)) statfs_more_ctor(void) +{ + cmd_register("statfs", "", + "show scoutfs file system information", statfs_more_cmd); }