diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index 64fd525d..447b4f8e 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -29,7 +29,18 @@ struct scoutfs_ioctl_walk_inodes_entry { * minor < major) as each increasingly significant value wraps around to * 0. * + * These indexes are not strictly consistent. The items that back these + * index entries aren't updated with cluster locks so they're not + * guaranteed to be visible the moment you read after writing. They're + * only visible when the transaction that updated them is synced. + * + * In addition, the seq indexes will only allow walking through sequence + * space that has been consistent. This prevents old dirty entries from + * becoming visible after newer stable entries are displayed. + * * If first is greater than last then the walk will return 0 entries. + * + * XXX invalidate before reading. */ struct scoutfs_ioctl_walk_inodes { struct scoutfs_ioctl_walk_inodes_entry first; @@ -153,4 +164,20 @@ struct scoutfs_ioctl_stat_more { #define SCOUTFS_IOC_STAT_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 7, \ struct scoutfs_ioctl_stat_more) +struct scoutfs_ioctl_item_cache_keys { + __u64 key_ptr; + __u64 key_len; + __u64 buf_ptr; + __u64 buf_len; + __u8 which; +} __packed; + +enum { + SCOUTFS_IOC_ITEM_CACHE_KEYS_ITEMS = 0, + SCOUTFS_IOC_ITEM_CACHE_KEYS_RANGES, +}; + +#define SCOUTFS_IOC_ITEM_CACHE_KEYS _IOW(SCOUTFS_IOCTL_MAGIC, 8, \ + struct scoutfs_ioctl_item_cache_keys) + #endif diff --git a/utils/src/item-cache-keys.c b/utils/src/item-cache-keys.c new file mode 100644 index 00000000..765f77d8 --- /dev/null +++ b/utils/src/item-cache-keys.c @@ -0,0 +1,131 @@ +#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" +#include "key.h" + +#define BUF_SIZE (64 * 1024) + +static int item_cache_keys(int argc, char **argv, int which) +{ + struct scoutfs_ioctl_item_cache_keys ick; + unsigned nr; + u16 key_len; + void *buf; + void *ptr; + int ret; + int fd; + + if (argc != 1) { + fprintf(stderr, "too many arguments, only scoutfs path needed"); + return -EINVAL; + } + + buf = malloc(BUF_SIZE); + if (!buf) { + ret = -errno; + fprintf(stderr, "failed to allocate buf: %s (%d)\n", + strerror(errno), errno); + return ret; + } + + fd = open(argv[0], O_RDONLY); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "failed to open '%s': %s (%d)\n", + argv[0], strerror(errno), errno); + free(buf); + return ret; + } + + ick.buf_ptr = (unsigned long)buf; + ick.buf_len = BUF_SIZE; + ick.key_ptr = 0; + ick.key_len = 0; + ick.which = which; + + nr = 1; + for (;;) { + ret = ioctl(fd, SCOUTFS_IOC_ITEM_CACHE_KEYS, &ick); + if (ret < 0) { + ret = -errno; + fprintf(stderr, "walk_inodes ioctl failed: %s (%d)\n", + strerror(errno), errno); + break; + } else if (ret == 0) { + break; + } + + ptr = (void *)(unsigned long)ick.buf_ptr; + + while (ret) { + if (ret < sizeof(key_len)) { + fprintf(stderr, "truncated len: %d\n", ret); + ret = -EINVAL; + break; + } + + memcpy(&key_len, ptr, sizeof(key_len)); + ptr += sizeof(key_len); + ret -= sizeof(key_len); + + if (ret < key_len) { + fprintf(stderr, "key len %d < buffer %d\n", + key_len, ret); + ret = -EINVAL; + break; + } + + print_key(ptr, key_len); + if (which == SCOUTFS_IOC_ITEM_CACHE_KEYS_ITEMS || + (nr % 2) == 0) + printf("\n"); + else + printf(" - "); + + ick.key_ptr = (unsigned long)ptr; + ick.key_len = key_len; + + ptr += key_len; + ret -= key_len; + + nr++; + } + if (ret < 0) + break; + } + + close(fd); + free(buf); + return ret; +}; + +static int item_keys(int argc, char **argv) +{ + return item_cache_keys(argc, argv, SCOUTFS_IOC_ITEM_CACHE_KEYS_ITEMS); +} + +static int range_keys(int argc, char **argv) +{ + return item_cache_keys(argc, argv, SCOUTFS_IOC_ITEM_CACHE_KEYS_RANGES); +} + +static void __attribute__((constructor)) item_cache_key_ctor(void) +{ + cmd_register("item-cache-keys", "", + "print range of indexed inodes", item_keys); + cmd_register("item-cache-range-keys", "", + "print range of indexed inodes", range_keys); +}