From 34c62824e5ad27ec911f6b7ceb80ac8f3c7f8f20 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 9 Jan 2017 16:21:13 -0800 Subject: [PATCH] Use a treap walker to print segments We were using a bitmap to record segments during manifest printing and then walking that bitmap to print segments. It's a little silly to have a second data structure record the referenced segments when we could just walk the manifest again to print the segments. So refactor node printing into a treap walker that calls a function for each node. Then we can have functions that print the node data structurs for each treap and then one that prints the segments that are referenced by manifest nodes. Signed-off-by: Zach Brown --- utils/src/print.c | 157 ++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 89 deletions(-) diff --git a/utils/src/print.c b/utils/src/print.c index 8e756233..f92c8af3 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -16,7 +16,6 @@ #include "cmd.h" #include "crc.h" #include "buddy.h" -#include "bitops.h" #include "item.h" /* XXX maybe these go somewhere */ @@ -231,8 +230,10 @@ static void print_segment_block(struct scoutfs_segment_block *sblk) le32_to_cpu(sblk->nr_items)); } -static int print_segment(int fd, u64 segno) +static int print_segment(int fd, struct scoutfs_treap_node *tnode) { + struct scoutfs_manifest_entry *ment = (void *)tnode->data; + u64 segno = le64_to_cpu(ment->segno); struct scoutfs_segment_block *sblk; int i; @@ -251,29 +252,6 @@ static int print_segment(int fd, u64 segno) return 0; } -static int print_segments(int fd, unsigned long *seg_map, u64 total_segs) -{ - int ret = 0; - int i = 0; - int err; - - for (i = 0; - (i = find_next_bit_le(seg_map, total_segs, i)) < total_segs; - i++) { - - err = print_segment(fd, i); - if (err && !ret) - ret = err; - } - - return ret; -} - -enum { - TREAP_MANIFEST, - TREAP_ALLOC, -}; - static void print_treap_ref(struct scoutfs_treap_ref *ref) { printf(" off %llu gen %llu aug_bits %x", @@ -281,31 +259,10 @@ static void print_treap_ref(struct scoutfs_treap_ref *ref) ref->aug_bits); } -static int print_treap_node(int fd, struct scoutfs_super_block *super, - unsigned treap, struct scoutfs_treap_ref *ref, - unsigned long *seg_map) +static void print_treap_node(struct scoutfs_treap_node *tnode) { - struct scoutfs_manifest_entry *ment; - struct scoutfs_alloc_region *reg; - struct scoutfs_treap_node *tnode; char valid_str[40]; __le32 crc; - u64 blkno; - void *blk; - u64 off; - int i; - - if (!ref->gen) - return 0; - - off = le64_to_cpu(ref->off); - blkno = le64_to_cpu(super->ring_blkno) + (off >> SCOUTFS_BLOCK_SHIFT); - - blk = read_block(fd, blkno); - if (!blk) - return -ENOMEM; - - tnode = blk + (off & SCOUTFS_BLOCK_MASK); crc = crc_node(tnode); if (crc != tnode->crc) @@ -322,48 +279,78 @@ static int print_treap_node(int fd, struct scoutfs_super_block *super, printf(" r:"); print_treap_ref(&tnode->right); printf("\n"); +} - switch(treap) { - case TREAP_MANIFEST: - ment = (void *)tnode->data; - printf(" ment: segno %llu seq %llu " - "first_len %u last_len %u level %u\n", - le64_to_cpu(ment->segno), - le64_to_cpu(ment->seq), - le16_to_cpu(ment->first_key_len), - le16_to_cpu(ment->last_key_len), - ment->level); - /* XXX verify, 'int nr' limits segno precision */ - set_bit_le(le64_to_cpu(ment->segno), seg_map); - break; +static int print_manifest_entry(int fd, struct scoutfs_treap_node *tnode) +{ + struct scoutfs_manifest_entry *ment = (void *)tnode->data; - case TREAP_ALLOC: - reg = (void *)tnode->data; - printf(" reg: index %llu bits", - le64_to_cpu(reg->index)); - for (i = 0; i < array_size(reg->bits); i++) - printf(" %016llx", le64_to_cpu(reg->bits[i])); - printf("\n"); - break; - } + print_treap_node(tnode); - print_treap_node(fd, super, treap, &tnode->left, seg_map); - print_treap_node(fd, super, treap, &tnode->right, seg_map); + printf(" ment: segno %llu seq %llu first_len %u last_len %u level %u\n", + le64_to_cpu(ment->segno), + le64_to_cpu(ment->seq), + le16_to_cpu(ment->first_key_len), + le16_to_cpu(ment->last_key_len), + ment->level); + + return 0; +} + +static int print_alloc_region(int fd, struct scoutfs_treap_node *tnode) +{ + struct scoutfs_alloc_region *reg = (void *)tnode->data; + int i; + + print_treap_node(tnode); + + printf(" reg: index %llu bits", le64_to_cpu(reg->index)); + for (i = 0; i < array_size(reg->bits); i++) + printf(" %016llx", le64_to_cpu(reg->bits[i])); + printf("\n"); + + return 0; +} + +typedef int (*tnode_func)(int fd, struct scoutfs_treap_node *tnode); + +static int walk_treap(int fd, struct scoutfs_super_block *super, + struct scoutfs_treap_ref *ref, tnode_func func) +{ + struct scoutfs_treap_node *tnode; + u64 blkno; + void *blk; + u64 off; + int ret; + + if (!ref->gen) + return 0; + + off = le64_to_cpu(ref->off); + blkno = le64_to_cpu(super->ring_blkno) + (off >> SCOUTFS_BLOCK_SHIFT); + + blk = read_block(fd, blkno); + if (!blk) + return -ENOMEM; + + tnode = blk + (off & SCOUTFS_BLOCK_MASK); + + ret = func(fd, tnode); + if (ret == 0) + ret = walk_treap(fd, super, &tnode->left, func) ?: + walk_treap(fd, super, &tnode->right, func); free(blk); - return 0; + return ret; } static int print_super_blocks(int fd) { struct scoutfs_super_block *super; struct scoutfs_super_block recent = { .hdr.seq = 0 }; - unsigned long *seg_map; char uuid_str[37]; __le64 *counts; - u64 total_segs; - u64 longs; int ret = 0; int err; int i; @@ -418,29 +405,21 @@ static int print_super_blocks(int fd) super = &recent; - /* XXX :P */ - total_segs = le64_to_cpu(super->total_blocks) / SCOUTFS_SEGMENT_BLOCKS; - longs = DIV_ROUND_UP(total_segs, BITS_PER_LONG); - seg_map = calloc(longs, sizeof(unsigned long)); - if (!seg_map) - return -ENOMEM; - printf("manifest treap:\n"); - ret = print_treap_node(fd, super, TREAP_MANIFEST, - &super->manifest.root.ref, seg_map); + ret = walk_treap(fd, super, &super->manifest.root.ref, + print_manifest_entry); printf("alloc treap:\n"); - err = print_treap_node(fd, super, TREAP_ALLOC, - &super->alloc_treap_root.ref, NULL); + err = walk_treap(fd, super, &super->alloc_treap_root.ref, + print_alloc_region); if (err && !ret) ret = err; - err = print_segments(fd, seg_map, total_segs); + err = walk_treap(fd, super, &super->manifest.root.ref, + print_segment); if (err && !ret) ret = err; - free(seg_map); - return ret; }