From 54044508fa6dfef17e9952a3b6f530802eaf6e44 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 5 Jul 2016 17:49:13 -0400 Subject: [PATCH] Add inodes-since command The kernel now has an ioctl to give us inode numbers with their sequence number for every inode that's been modified since a given tree update sequence number. Update mkfs and print to the on-disk format changes and add a trivial inodes-since command which calls the ioctl and prints the results. Signed-off-by: Zach Brown --- utils/src/format.h | 5 +++ utils/src/ioctl.h | 19 ++++++++++ utils/src/mkfs.c | 1 + utils/src/print.c | 5 +-- utils/src/since.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 utils/src/since.c diff --git a/utils/src/format.h b/utils/src/format.h index 5210e7cb..e3112b3e 100644 --- a/utils/src/format.h +++ b/utils/src/format.h @@ -91,9 +91,14 @@ struct scoutfs_btree_block { __le16 nr_items; } __packed; +/* + * The item sequence number is set to the dirty block's sequence number + * when the item is modified. It is not changed by splits or merges. + */ struct scoutfs_btree_item { struct scoutfs_key key; struct scoutfs_treap_node tnode; + __le64 seq; __le16 val_len; char val[0]; } __packed; diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index 1accfdae..7ea6e5f2 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -27,4 +27,23 @@ struct scoutfs_trace_record { #define SCOUTFS_IOC_GET_TRACE_RECORDS _IOW(SCOUTFS_IOCTL_MAGIC, 2, \ struct scoutfs_ioctl_buf) +struct scoutfs_ioctl_ino_seq { + __u64 ino; + __u64 seq; +} __packed; + +struct scoutfs_ioctl_inodes_since { + __u64 first_ino; + __u64 last_ino; + __u64 seq; + struct scoutfs_ioctl_buf results; +} __packed; + +/* + * Adds entries to the user's buffer for each inode whose sequence + * number is greater than or equal to the given seq. + */ +#define SCOUTFS_IOC_INODES_SINCE _IOW(SCOUTFS_IOCTL_MAGIC, 3, \ + struct scoutfs_ioctl_inodes_since) + #endif diff --git a/utils/src/mkfs.c b/utils/src/mkfs.c index af2a9661..48e6e1b0 100644 --- a/utils/src/mkfs.c +++ b/utils/src/mkfs.c @@ -125,6 +125,7 @@ static int write_new_fs(char *path, int fd) bt->nr_items = cpu_to_le16(1); item = (void *)(bt + 1); + item->seq = cpu_to_le64(1); item->key = root_key; item->tnode.parent = 0; item->tnode.left = 0; diff --git a/utils/src/print.c b/utils/src/print.c index 7e51370e..e8f8f61e 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -99,9 +99,10 @@ static void print_block_ref(struct scoutfs_block_ref *ref) static void print_btree_item(unsigned int off, struct scoutfs_btree_item *item, u8 level) { - printf(" item: key "SKF" val_len %u off %u tnode: parent %u left %u right %u " + printf(" item: key "SKF" seq %llu val_len %u off %u tnode: parent %u left %u right %u " "prio %x\n", - SKA(&item->key), le16_to_cpu(item->val_len), off, + SKA(&item->key), le64_to_cpu(item->seq), + le16_to_cpu(item->val_len), off, le16_to_cpu(item->tnode.parent), le16_to_cpu(item->tnode.left), le16_to_cpu(item->tnode.right), diff --git a/utils/src/since.c b/utils/src/since.c new file mode 100644 index 00000000..4fe22572 --- /dev/null +++ b/utils/src/since.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sparse.h" +#include "util.h" +#include "ioctl.h" +#include "cmd.h" + +static int since_cmd(int argc, char **argv) +{ + struct scoutfs_ioctl_inodes_since args; + struct scoutfs_ioctl_ino_seq *iseq; + int len = 4 * 1024 * 1024; + char *endptr; + u64 nrs[3]; + void *ptr; + int ret; + int fd; + u64 n; + int i; + + if (argc != 4) { + fprintf(stderr, "must specify seq and path\n"); + return -EINVAL; + } + + for (i = 0; i < array_size(nrs); i++) { + n = strtoull(argv[i], &endptr, 0); + if (*endptr != '\0' || + ((n == LLONG_MIN || n == LLONG_MAX) && errno == ERANGE)) { + fprintf(stderr, "error parsing 64bit value '%s'\n", + argv[i]); + return -EINVAL; + } + nrs[i] = n; + } + + fd = open(argv[3], O_RDONLY); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "failed to open '%s': %s (%d)\n", + argv[3], strerror(errno), errno); + return ret; + } + + ptr = malloc(len); + if (!ptr) { + fprintf(stderr, "must specify seq and path\n"); + close(fd); + return -EINVAL; + } + + args.first_ino = nrs[0]; + args.last_ino = nrs[1]; + args.seq = nrs[2]; + args.results.ptr = (intptr_t)ptr; + args.results.len = len; + + ret = ioctl(fd, SCOUTFS_IOC_INODES_SINCE, &args); + if (ret < 0) { + ret = -errno; + fprintf(stderr, "inodes_since ioctl failed: %s (%d)\n", + strerror(errno), errno); + goto out; + } + + n = ret / sizeof(*iseq); + for (i = 0, iseq = ptr; i < n; i++, iseq++) + printf("ino %llu seq %llu\n", iseq->ino, iseq->seq); + +out: + free(ptr); + close(fd); + return ret; +}; + +static void __attribute__((constructor)) since_ctor(void) +{ + cmd_register("inodes-since", " ", + "print inodes modified since seq #", since_cmd); +}