diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index 864b9b8f..822147d3 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -10,6 +10,27 @@ struct scoutfs_ioctl_walk_inodes_entry { __u64 ino; } __packed; +/* + * Walk inodes in an index that is sorted by one of their fields. + * + * Each index is built from generic index items that have major and + * minor values that are set to the field being indexed. In time + * indices, for example, major is seconds and minor is nanoseconds. + * + * @first The first index entry that can be returned. + * @last The last index entry that can be returned. + * @entries_ptr Pointer to emory containing buffer for entry results. + * @nr_entries The number of entries that can fit in the buffer. + * @index Which index to walk, enumerated in _WALK_INODES_ constants. + * + * To start iterating first can be memset to 0 and last to 0xff. Then + * after each set of results first can be set to the last entry returned + * and then the fields can be incremented in reverse sort order (ino < + * minor < major) as each increasingly significant value wraps around to + * 0. + * + * If first is greater than last then the walk will return 0 entries. + */ struct scoutfs_ioctl_walk_inodes { struct scoutfs_ioctl_walk_inodes_entry first; struct scoutfs_ioctl_walk_inodes_entry last; @@ -107,4 +128,25 @@ struct scoutfs_ioctl_stage { #define SCOUTFS_IOC_STAGE _IOW(SCOUTFS_IOCTL_MAGIC, 6, \ struct scoutfs_ioctl_stage) +/* + * Give the user inode fields that are not otherwise visible. statx() + * isn't always available and xattrs are relatively expensive. + * + * @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_stat_more { + __u64 valid_bytes; + __u64 data_version; +} __packed; + +#define SCOUTFS_IOC_STAT_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 7, \ + struct scoutfs_ioctl_stat_more) + #endif diff --git a/utils/src/stage_release.c b/utils/src/stage_release.c index 581cb69f..61750b1a 100644 --- a/utils/src/stage_release.c +++ b/utils/src/stage_release.c @@ -193,41 +193,3 @@ static void __attribute__((constructor)) release_ctor(void) cmd_register("release", " ", "mark file region offline and free extents", release_cmd); } - -static int data_version_cmd(int argc, char **argv) -{ - u64 vers; - int ret; - int fd; - - if (argc != 1) { - fprintf(stderr, "must specify path\n"); - return -EINVAL; - } - - fd = open(argv[0], O_RDWR); - if (fd < 0) { - ret = -errno; - fprintf(stderr, "failed to open '%s': %s (%d)\n", - argv[0], strerror(errno), errno); - return ret; - } - - ret = ioctl(fd, SCOUTFS_IOC_DATA_VERSION, &vers); - if (ret < 0) { - ret = -errno; - fprintf(stderr, "data version ioctl failed: %s (%d)\n", - strerror(errno), errno); - } else { - printf("%llu\n", vers); - } - - close(fd); - return ret; -}; - -static void __attribute__((constructor)) data_version_ctor(void) -{ - cmd_register("data_version", "", - "print the file's data version", data_version_cmd); -} diff --git a/utils/src/stat.c b/utils/src/stat.c new file mode 100644 index 00000000..11d0972e --- /dev/null +++ b/utils/src/stat.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sparse.h" +#include "util.h" +#include "format.h" +#include "ioctl.h" +#include "cmd.h" + +static int stat_more_cmd(int argc, char **argv) +{ + struct scoutfs_ioctl_stat_more stm; + char *path; + int ret; + int fd; + int i; + + if (argc == 0) { + fprintf(stderr, "must specify at least one path argument\n"); + return -EINVAL; + } + + for (i = 0; i < argc; i++) { + path = argv[i]; + + fd = open(path, O_RDONLY); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "failed to open '%s': %s (%d)\n", + path, strerror(errno), errno); + continue; + } + + memset(&stm, 0, sizeof(stm)); + stm.valid_bytes = sizeof(stm); + + ret = ioctl(fd, SCOUTFS_IOC_STAT_MORE, &stm); + if (ret < 0) { + ret = -errno; + fprintf(stderr, "stat_more ioctl failed on '%s': " + "%s (%d)\n", path, strerror(errno), errno); + } else { + printf(" File: '%s'\n" + " data_version: %-20llu\n", + path, stm.data_version); + } + + close(fd); + } + + return 0; +} + +static void __attribute__((constructor)) stat_more_ctor(void) +{ + cmd_register("stat", "", + "print scoutfs stat information for path", stat_more_cmd); +}