From 7bbe49fde2afc21120e87ee29a47096dff9d6f32 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Thu, 13 Jul 2017 14:53:07 -0700 Subject: [PATCH] scoutfs-utils: sort keys by zones, then types Our item cache protocol is tied to holding DLM locks which cover a region of the item namespace. We want locks to cover all the data associated with an inode and other locks to cover the indexes. So we resort the items first by major (index, fs) then by inode type (inode, dirent, etc). Signed-off-by: Zach Brown --- utils/src/format.h | 125 +++++++++++++++++++++---------------- utils/src/key.c | 152 +++++++++++++++++++++++++++------------------ utils/src/mkfs.c | 108 ++++++++++++++++---------------- utils/src/print.c | 84 ++++++++++++++++++------- 4 files changed, 280 insertions(+), 189 deletions(-) diff --git a/utils/src/format.h b/utils/src/format.h index b1bbdbbd..6251c8f8 100644 --- a/utils/src/format.h +++ b/utils/src/format.h @@ -50,12 +50,6 @@ struct scoutfs_block_header { __le64 blkno; } __packed; -/* - * The largest possible btree has 2^64 bytes worth of segments with - * the largest possible keys in a pathologically sparse btree where - * all the nodes are half full. - */ - /* * Assert that we'll be able to represent all possible keys with 8 64bit * primary sort values. @@ -94,9 +88,6 @@ enum { SCOUTFS_BTREE_BIT_HALF2 = (1 << 1), }; -#define SCOUTFS_BTREE_HALF_BITS \ - (SCOUTFS_BTREE_BIT_HALF1 | SCOUTFS_BTREE_BIT_HALF2) - struct scoutfs_btree_ref { __le64 blkno; __le64 seq; @@ -165,9 +156,8 @@ struct scoutfs_manifest { * segment key in the manifest btree key. Both of their keys are in the * value. * - * Level 1 segments are sorted by their key before their seq so the - * btree header has the key and the seq is in the footer. Only their - * last key is in the value. + * Level 1 segments are sorted by their first key so their last key is + * in the value. * * We go to all this trouble so that we can communicate a version of the * manifest with one btree root, have dense btree keys which are used as @@ -246,73 +236,78 @@ struct scoutfs_segment_block { } __packed; /* - * Currently we sort keys by the numeric value of the types, but that - * isn't necessary. We could have an arbitrary sort order. So we don't - * have to stress about cleverly allocating the types. + * Keys are first sorted by major key zones. */ -#define SCOUTFS_INODE_KEY 1 -#define SCOUTFS_XATTR_KEY 3 -#define SCOUTFS_DIRENT_KEY 5 -#define SCOUTFS_READDIR_KEY 6 -#define SCOUTFS_LINK_BACKREF_KEY 7 -#define SCOUTFS_SYMLINK_KEY 8 -#define SCOUTFS_FILE_EXTENT_KEY 9 -#define SCOUTFS_ORPHAN_KEY 10 -#define SCOUTFS_FREE_EXTENT_BLKNO_KEY 11 -#define SCOUTFS_FREE_EXTENT_BLOCKS_KEY 12 -#define SCOUTFS_INODE_INDEX_CTIME_KEY 13 /* don't forget first and last */ -#define SCOUTFS_INODE_INDEX_MTIME_KEY 14 -#define SCOUTFS_INODE_INDEX_SIZE_KEY 15 -#define SCOUTFS_INODE_INDEX_META_SEQ_KEY 16 -#define SCOUTFS_INODE_INDEX_DATA_SEQ_KEY 17 -/* not found in the fs */ -#define SCOUTFS_MAX_UNUSED_KEY 253 -#define SCOUTFS_NET_ADDR_KEY 254 -#define SCOUTFS_NET_LISTEN_KEY 255 +#define SCOUTFS_INODE_INDEX_ZONE 1 +#define SCOUTFS_NODE_ZONE 2 +#define SCOUTFS_FS_ZONE 3 + +/* inode index zone */ +#define SCOUTFS_INODE_INDEX_CTIME_TYPE 1 +#define SCOUTFS_INODE_INDEX_MTIME_TYPE 2 +#define SCOUTFS_INODE_INDEX_SIZE_TYPE 3 +#define SCOUTFS_INODE_INDEX_META_SEQ_TYPE 4 +#define SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE 5 -#define SCOUTFS_INODE_INDEX_FIRST SCOUTFS_INODE_INDEX_CTIME_KEY -#define SCOUTFS_INODE_INDEX_LAST SCOUTFS_INODE_INDEX_DATA_SEQ_KEY #define SCOUTFS_INODE_INDEX_NR \ - (SCOUTFS_INODE_INDEX_LAST - SCOUTFS_INODE_INDEX_FIRST + 1) + (SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE - SCOUTFS_INODE_INDEX_CTIME_TYPE + 1) + +/* node zone */ +#define SCOUTFS_FREE_EXTENT_BLKNO_TYPE 11 +#define SCOUTFS_FREE_EXTENT_BLOCKS_TYPE 12 + +/* fs zone */ +#define SCOUTFS_INODE_TYPE 1 +#define SCOUTFS_XATTR_TYPE 2 +#define SCOUTFS_DIRENT_TYPE 3 +#define SCOUTFS_READDIR_TYPE 4 +#define SCOUTFS_LINK_BACKREF_TYPE 5 +#define SCOUTFS_SYMLINK_TYPE 6 +#define SCOUTFS_FILE_EXTENT_TYPE 7 +#define SCOUTFS_ORPHAN_TYPE 8 + +/* XXX don't need these now that we have dlm lock spaces and resources */ +#define SCOUTFS_NET_ADDR_TYPE 254 +#define SCOUTFS_NET_LISTEN_TYPE 255 /* value is struct scoutfs_inode */ struct scoutfs_inode_key { - __u8 type; + __u8 zone; __be64 ino; + __u8 type; } __packed; /* value is struct scoutfs_dirent without the name */ struct scoutfs_dirent_key { - __u8 type; + __u8 zone; __be64 ino; + __u8 type; __u8 name[0]; } __packed; /* value is struct scoutfs_dirent with the name */ struct scoutfs_readdir_key { - __u8 type; + __u8 zone; __be64 ino; + __u8 type; __be64 pos; } __packed; /* value is empty */ struct scoutfs_link_backref_key { - __u8 type; + __u8 zone; __be64 ino; + __u8 type; __be64 dir_ino; __u8 name[0]; } __packed; -/* no value */ -struct scoutfs_orphan_key { - __u8 type; - __be64 ino; -} __packed; /* no value */ struct scoutfs_file_extent_key { - __u8 type; + __u8 zone; __be64 ino; + __u8 type; __be64 last_blk_off; __be64 last_blkno; __be64 blocks; @@ -323,23 +318,34 @@ struct scoutfs_file_extent_key { /* no value */ struct scoutfs_free_extent_blkno_key { - __u8 type; + __u8 zone; __be64 node_id; + __u8 type; __be64 last_blkno; __be64 blocks; } __packed; struct scoutfs_free_extent_blocks_key { - __u8 type; + __u8 zone; __be64 node_id; + __u8 type; __be64 blocks; __be64 last_blkno; } __packed; -/* value is each item's part of the full xattr value for the off/len */ -struct scoutfs_xattr_key { +/* no value */ +struct scoutfs_orphan_key { + __u8 zone; + __be64 node_id; __u8 type; __be64 ino; +} __packed; + +/* value is each item's part of the full xattr value for the off/len */ +struct scoutfs_xattr_key { + __u8 zone; + __be64 ino; + __u8 type; __u8 name[0]; } __packed; @@ -355,8 +361,9 @@ struct scoutfs_xattr_val_header { /* size determines nr needed to store full target path in their values */ struct scoutfs_symlink_key { - __u8 type; + __u8 zone; __be64 ino; + __u8 type; __u8 nr; } __packed; @@ -366,6 +373,7 @@ struct scoutfs_betimespec { } __packed; struct scoutfs_inode_index_key { + __u8 zone; __u8 type; __be64 major; __be32 minor; @@ -498,6 +506,19 @@ enum { #define SCOUTFS_XATTR_MAX_PARTS \ DIV_ROUND_UP(SCOUTFS_XATTR_MAX_SIZE, SCOUTFS_XATTR_PART_SIZE) +/* + * structures used by dlm + */ +struct scoutfs_lock_name { + __u8 zone; + __u8 type; + __le64 first; + __le64 second; +} __packed; + +#define SCOUTFS_LOCK_INODE_GROUP_NR 1024 +#define SCOUTFS_LOCK_INODE_GROUP_MASK (SCOUTFS_LOCK_INODE_GROUP_NR - 1) +#define SCOUTFS_LOCK_INODE_GROUP_OFFSET (~0ULL) /* * messages over the wire. diff --git a/utils/src/key.c b/utils/src/key.c index 1487f9e3..46bc1420 100644 --- a/utils/src/key.c +++ b/utils/src/key.c @@ -10,14 +10,16 @@ /* * This is mechanically derived from scoutfs_key_str() in the kernel: - * - s/key->data/key_data/ - * - s/key->key_len/key_len/ - * - s/return snprintf_null(buf, size, /return printf(/ + * - :.,$s/key->data/key_data/g + * - :.,$s/key->key_len/key_len/g + * - :.,$s/return snprintf_null(buf, size, /return printf(/g */ int print_key(void *key_data, unsigned key_len) { + struct scoutfs_inode_key *ikey; + u8 zone = 0; + u8 type = 0; int len; - u8 type; if (key_data == NULL) return printf("[NULL]"); @@ -25,21 +27,88 @@ int print_key(void *key_data, unsigned key_len) if (key_len == 0) return printf("[0 len]"); - type = *(u8 *)key_data; + zone = *(u8 *)key_data; - switch(type) { + /* handle smaller and unknown zones, fall through to fs types */ + switch(zone) { + case SCOUTFS_INODE_INDEX_ZONE: { + struct scoutfs_inode_index_key *ikey = key_data; + static char *type_strings[] = { + [SCOUTFS_INODE_INDEX_CTIME_TYPE] = "ctm", + [SCOUTFS_INODE_INDEX_MTIME_TYPE] = "mtm", + [SCOUTFS_INODE_INDEX_SIZE_TYPE] = "siz", + [SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = "msq", + [SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = "dsq", + }; - case SCOUTFS_INODE_KEY: { + if (key_len < sizeof(struct scoutfs_inode_index_key)) + break; + + if (type_strings[ikey->type]) + return printf("iin.%s.%llu.%u.%llu", + type_strings[ikey->type], + be64_to_cpu(ikey->major), + be32_to_cpu(ikey->minor), + be64_to_cpu(ikey->ino)); + else + return printf("[iin type %u?]", + ikey->type); + } + + /* node zone keys start with zone, node, type */ + case SCOUTFS_NODE_ZONE: { + struct scoutfs_free_extent_blkno_key *fkey = key_data; + + static char *type_strings[] = { + [SCOUTFS_FREE_EXTENT_BLKNO_TYPE] = "fno", + [SCOUTFS_FREE_EXTENT_BLOCKS_TYPE] = "fks", + }; + + switch(fkey->type) { + case SCOUTFS_ORPHAN_TYPE: { + struct scoutfs_orphan_key *okey = key_data; + + if (key_len < sizeof(struct scoutfs_orphan_key)) + break; + return printf("nod.%llu.orp.%llu", + be64_to_cpu(okey->node_id), + be64_to_cpu(okey->ino)); + } + + case SCOUTFS_FREE_EXTENT_BLKNO_TYPE: + case SCOUTFS_FREE_EXTENT_BLOCKS_TYPE: + return printf("nod.%llu.%s.%llu.%llu", + be64_to_cpu(fkey->node_id), + type_strings[fkey->type], + be64_to_cpu(fkey->last_blkno), + be64_to_cpu(fkey->blocks)); + default: + return printf("[nod type %u?]", + fkey->type); + } + } + + case SCOUTFS_FS_ZONE: + break; + + default: + return printf("[zone %u?]", zone); + } + + /* everything in the fs tree starts with zone, ino, type */ + ikey = key_data; + switch(ikey->type) { + case SCOUTFS_INODE_TYPE: { struct scoutfs_inode_key *ikey = key_data; if (key_len < sizeof(struct scoutfs_inode_key)) break; - return printf("ino.%llu", + return printf("fs.%llu.ino", be64_to_cpu(ikey->ino)); } - case SCOUTFS_XATTR_KEY: { + case SCOUTFS_XATTR_TYPE: { struct scoutfs_xattr_key *xkey = key_data; len = (int)key_len - offsetof(struct scoutfs_xattr_key, @@ -47,53 +116,53 @@ int print_key(void *key_data, unsigned key_len) if (len <= 0) break; - return printf("xat.%llu.%.*s", + return printf("fs.%llu.xat.%.*s", be64_to_cpu(xkey->ino), len, xkey->name); } - case SCOUTFS_DIRENT_KEY: { + case SCOUTFS_DIRENT_TYPE: { struct scoutfs_dirent_key *dkey = key_data; len = (int)key_len - sizeof(struct scoutfs_dirent_key); if (len <= 0) break; - return printf("dnt.%llu.%.*s", + return printf("fs.%llu.dnt.%.*s", be64_to_cpu(dkey->ino), len, dkey->name); } - case SCOUTFS_READDIR_KEY: { + case SCOUTFS_READDIR_TYPE: { struct scoutfs_readdir_key *rkey = key_data; - return printf("rdr.%llu.%llu", + return printf("fs.%llu.rdr.%llu", be64_to_cpu(rkey->ino), be64_to_cpu(rkey->pos)); } - case SCOUTFS_LINK_BACKREF_KEY: { + case SCOUTFS_LINK_BACKREF_TYPE: { struct scoutfs_link_backref_key *lkey = key_data; len = (int)key_len - sizeof(*lkey); if (len <= 0) break; - return printf("lbr.%llu.%llu.%.*s", + return printf("fs.%llu.lbr.%llu.%.*s", be64_to_cpu(lkey->ino), be64_to_cpu(lkey->dir_ino), len, lkey->name); } - case SCOUTFS_SYMLINK_KEY: { + case SCOUTFS_SYMLINK_TYPE: { struct scoutfs_symlink_key *skey = key_data; - return printf("sym.%llu", + return printf("fs.%llu.sym", be64_to_cpu(skey->ino)); } - case SCOUTFS_FILE_EXTENT_KEY: { + case SCOUTFS_FILE_EXTENT_TYPE: { struct scoutfs_file_extent_key *ekey = key_data; - return printf("ext.%llu.%llu.%llu.%llu.%x", + return printf("fs.%llu.ext.%llu.%llu.%llu.%x", be64_to_cpu(ekey->ino), be64_to_cpu(ekey->last_blk_off), be64_to_cpu(ekey->last_blkno), @@ -101,48 +170,11 @@ int print_key(void *key_data, unsigned key_len) ekey->flags); } - case SCOUTFS_ORPHAN_KEY: { - struct scoutfs_orphan_key *okey = key_data; - - return printf("orp.%llu", - be64_to_cpu(okey->ino)); - } - - case SCOUTFS_FREE_EXTENT_BLKNO_KEY: - case SCOUTFS_FREE_EXTENT_BLOCKS_KEY: { - struct scoutfs_free_extent_blkno_key *fkey = key_data; - - return printf("%s.%llu.%llu.%llu", - fkey->type == SCOUTFS_FREE_EXTENT_BLKNO_KEY ? "fel" : - "fes", - be64_to_cpu(fkey->node_id), - be64_to_cpu(fkey->last_blkno), - be64_to_cpu(fkey->blocks)); - } - - case SCOUTFS_INODE_INDEX_CTIME_KEY: - case SCOUTFS_INODE_INDEX_MTIME_KEY: - case SCOUTFS_INODE_INDEX_SIZE_KEY: - case SCOUTFS_INODE_INDEX_META_SEQ_KEY: - case SCOUTFS_INODE_INDEX_DATA_SEQ_KEY: { - struct scoutfs_inode_index_key *ikey = key_data; - - return printf("%s.%llu.%u.%llu", - ikey->type == SCOUTFS_INODE_INDEX_CTIME_KEY ? "ctm" : - ikey->type == SCOUTFS_INODE_INDEX_MTIME_KEY ? "mtm" : - ikey->type == SCOUTFS_INODE_INDEX_SIZE_KEY ? "siz" : - ikey->type == SCOUTFS_INODE_INDEX_META_SEQ_KEY ? "msq" : - ikey->type == SCOUTFS_INODE_INDEX_DATA_SEQ_KEY ? "dsq" : - "uii", be64_to_cpu(ikey->major), - be32_to_cpu(ikey->minor), - be64_to_cpu(ikey->ino)); - } - default: - return printf("[unknown type %u len %u]", - type, key_len); + return printf("[fs type %u?]", type); } - return printf("[truncated type %u len %u]", + return printf("[fs type %u trunc len %u]", type, key_len); + } diff --git a/utils/src/mkfs.c b/utils/src/mkfs.c index 1388009e..6182d199 100644 --- a/utils/src/mkfs.c +++ b/utils/src/mkfs.c @@ -242,32 +242,34 @@ static int write_new_fs(char *path, int fd) bt->nr_items = cpu_to_le16(1); /* btree item allocated from the back of the block */ - idx_key = (void *)bt + SCOUTFS_BLOCK_SIZE - sizeof(*idx_key); - mval = (void *)idx_key - sizeof(*mval); - ikey = (void *)mval - sizeof(*ikey); - mkey = (void *)ikey - sizeof(*mkey); + ikey = (void *)bt + SCOUTFS_BLOCK_SIZE - sizeof(*ikey); + mval = (void *)ikey - sizeof(*mval); + idx_key = (void *)mval - sizeof(*idx_key); + mkey = (void *)idx_key - sizeof(*mkey); btitem = (void *)mkey - sizeof(*btitem); bt->item_hdrs[0].off = cpu_to_le16((long)btitem - (long)bt); bt->free_end = bt->item_hdrs[0].off; btitem->key_len = cpu_to_le16(sizeof(struct scoutfs_manifest_btree_key) + - sizeof(struct scoutfs_inode_key)); - btitem->val_len = cpu_to_le16(sizeof(struct scoutfs_manifest_btree_val) + sizeof(struct scoutfs_inode_index_key)); + btitem->val_len = cpu_to_le16(sizeof(struct scoutfs_manifest_btree_val) + + sizeof(struct scoutfs_inode_key)); mkey->level = 1; - ikey->type = SCOUTFS_INODE_KEY; - ikey->ino = cpu_to_be64(SCOUTFS_ROOT_INO); + idx_key->zone = SCOUTFS_INODE_INDEX_ZONE; + idx_key->type = SCOUTFS_INODE_INDEX_CTIME_TYPE; + idx_key->major = cpu_to_be64(tv.tv_sec); + idx_key->minor = cpu_to_be32(tv.tv_usec * 1000); + idx_key->ino = cpu_to_be64(SCOUTFS_ROOT_INO); mval->segno = cpu_to_le64(first_segno); mval->seq = cpu_to_le64(1); - mval->first_key_len = cpu_to_le16(sizeof(struct scoutfs_inode_key)); - mval->last_key_len = cpu_to_le16(sizeof(struct scoutfs_inode_index_key)); - idx_key->type = SCOUTFS_INODE_INDEX_META_SEQ_KEY; - idx_key->major = cpu_to_be64(0); - idx_key->minor = 0; - idx_key->ino = cpu_to_be64(SCOUTFS_ROOT_INO); + mval->first_key_len = cpu_to_le16(sizeof(struct scoutfs_inode_index_key)); + mval->last_key_len = cpu_to_le16(sizeof(struct scoutfs_inode_key)); + ikey->zone = SCOUTFS_FS_ZONE; + ikey->ino = cpu_to_be64(SCOUTFS_ROOT_INO); + ikey->type = SCOUTFS_INODE_TYPE; bt->crc = cpu_to_le32(crc_btree_block(bt)); @@ -287,6 +289,42 @@ static int write_new_fs(char *path, int fd) prev_link = &sblk->skip_links[0]; item = (void *)(sblk + 1); + *prev_link = cpu_to_le32((long)item -(long)sblk); + prev_link = &item->skip_links[0]; + + /* write the root inode index keys */ + for (i = SCOUTFS_INODE_INDEX_CTIME_TYPE; + i <= SCOUTFS_INODE_INDEX_META_SEQ_TYPE; i++) { + + item->key_len = cpu_to_le16(sizeof(*idx_key)); + item->val_len = 0; + item->nr_links = 1; + + idx_key = (void *)&item->skip_links[1]; + idx_key->zone = SCOUTFS_INODE_INDEX_ZONE; + idx_key->type = i; + idx_key->ino = cpu_to_be64(SCOUTFS_ROOT_INO); + + switch(i) { + case SCOUTFS_INODE_INDEX_CTIME_TYPE: + case SCOUTFS_INODE_INDEX_MTIME_TYPE: + idx_key->major = cpu_to_be64(tv.tv_sec); + idx_key->minor = cpu_to_be32(tv.tv_usec * 1000); + break; + default: + idx_key->major = cpu_to_be64(0); + idx_key->minor = 0; + break; + } + + + item = (void *)(idx_key + 1); + *prev_link = cpu_to_le32((long)item -(long)sblk); + prev_link = &item->skip_links[0]; + } + + sblk->last_item_off = cpu_to_le32((long)item - (long)sblk); + ikey = (void *)&item->skip_links[1]; inode = (void *)ikey + sizeof(struct scoutfs_inode_key); @@ -294,8 +332,9 @@ static int write_new_fs(char *path, int fd) item->val_len = cpu_to_le16(sizeof(struct scoutfs_inode)); item->nr_links = 1; - ikey->type = SCOUTFS_INODE_KEY; + ikey->zone = SCOUTFS_FS_ZONE; ikey->ino = cpu_to_be64(SCOUTFS_ROOT_INO); + ikey->type = SCOUTFS_INODE_TYPE; inode->next_readdir_pos = cpu_to_le64(2); inode->nlink = cpu_to_le32(SCOUTFS_DIRENT_FIRST_POS); @@ -307,44 +346,7 @@ static int write_new_fs(char *path, int fd) inode->mtime.sec = inode->atime.sec; inode->mtime.nsec = inode->atime.nsec; - *prev_link = cpu_to_le32((long)item -(long)sblk); - prev_link = &item->skip_links[0]; - - item = (void *)inode + sizeof(struct scoutfs_inode); - idx_key = (void *)&item->skip_links[1]; - - /* write the root inode index keys */ - for (i = SCOUTFS_INODE_INDEX_CTIME_KEY; - i <= SCOUTFS_INODE_INDEX_META_SEQ_KEY; i++) { - - item->key_len = cpu_to_le16(sizeof(*idx_key)); - item->val_len = 0; - item->nr_links = 1; - - idx_key->type = i; - idx_key->ino = cpu_to_be64(SCOUTFS_ROOT_INO); - - switch(i) { - case SCOUTFS_INODE_INDEX_CTIME_KEY: - case SCOUTFS_INODE_INDEX_MTIME_KEY: - idx_key->major = cpu_to_be64(tv.tv_sec); - idx_key->minor = cpu_to_be32(tv.tv_usec * 1000); - break; - default: - idx_key->major = cpu_to_be64(0); - idx_key->minor = 0; - break; - } - - *prev_link = cpu_to_le32((long)item -(long)sblk); - prev_link = &item->skip_links[0]; - - sblk->last_item_off = cpu_to_le32((long)item - (long)sblk); - - item = (void *)(idx_key + 1); - idx_key = (void *)&item->skip_links[1]; - } - + item = (void *)(inode + 1); sblk->total_bytes = cpu_to_le32((long)item - (long)sblk); ret = pwrite(fd, sblk, SCOUTFS_SEGMENT_SIZE, diff --git a/utils/src/print.c b/utils/src/print.c index 6462e161..3b3b4367 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -216,7 +216,7 @@ static void print_free_extent(void *key, int key_len, void *val, int val_len) u64 blkno; char *str; - if (blk->type == SCOUTFS_FREE_EXTENT_BLKNO_KEY) { + if (blk->type == SCOUTFS_FREE_EXTENT_BLKNO_TYPE) { str = "free (blkno)"; node_id = be64_to_cpu(blk->node_id); last_blkno = be64_to_cpu(blk->last_blkno); @@ -245,23 +245,58 @@ static void print_inode_index(void *key, int key_len, void *val, int val_len) typedef void (*print_func_t)(void *key, int key_len, void *val, int val_len); -static print_func_t printers[] = { - [SCOUTFS_INODE_KEY] = print_inode, - [SCOUTFS_XATTR_KEY] = print_xattr, - [SCOUTFS_ORPHAN_KEY] = print_orphan, - [SCOUTFS_DIRENT_KEY] = print_dirent, - [SCOUTFS_READDIR_KEY] = print_readdir, - [SCOUTFS_SYMLINK_KEY] = print_symlink, - [SCOUTFS_LINK_BACKREF_KEY] = print_link_backref, - [SCOUTFS_FILE_EXTENT_KEY] = print_file_extent, - [SCOUTFS_FREE_EXTENT_BLKNO_KEY] = print_free_extent, - [SCOUTFS_FREE_EXTENT_BLOCKS_KEY] = print_free_extent, - [SCOUTFS_INODE_INDEX_CTIME_KEY] = print_inode_index, - [SCOUTFS_INODE_INDEX_MTIME_KEY] = print_inode_index, - [SCOUTFS_INODE_INDEX_SIZE_KEY] = print_inode_index, - [SCOUTFS_INODE_INDEX_META_SEQ_KEY] = print_inode_index, - [SCOUTFS_INODE_INDEX_DATA_SEQ_KEY] = print_inode_index, -}; +static print_func_t find_printer(u8 zone, u8 type) +{ + if (zone == SCOUTFS_INODE_INDEX_ZONE && + type >= SCOUTFS_INODE_INDEX_CTIME_TYPE && + type <= SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE) + return print_inode_index; + + if (zone == SCOUTFS_NODE_ZONE) { + if (type >= SCOUTFS_FREE_EXTENT_BLKNO_TYPE && + type <= SCOUTFS_FREE_EXTENT_BLOCKS_TYPE) + return print_free_extent; + if (type == SCOUTFS_ORPHAN_TYPE) + return print_orphan; + } + + if (zone == SCOUTFS_FS_ZONE) { + switch(type) { + case SCOUTFS_INODE_TYPE: return print_inode; + case SCOUTFS_XATTR_TYPE: return print_xattr; + case SCOUTFS_DIRENT_TYPE: return print_dirent; + case SCOUTFS_READDIR_TYPE: return print_readdir; + case SCOUTFS_SYMLINK_TYPE: return print_symlink; + case SCOUTFS_LINK_BACKREF_TYPE: return print_link_backref; + case SCOUTFS_FILE_EXTENT_TYPE: return print_file_extent; + } + } + + return NULL; +} + +static void find_zone_type(void *key, u8 *zone, u8 *type) +{ + struct scoutfs_inode_index_key *idx_key = key; + struct scoutfs_inode_key *ikey = key; + struct scoutfs_orphan_key *okey = key; + + *zone = *(u8 *)key; + + switch (*zone) { + case SCOUTFS_INODE_INDEX_ZONE: + *type = idx_key->type; + break; + case SCOUTFS_NODE_ZONE: + *type = okey->type; + break; + case SCOUTFS_FS_ZONE: + *type = ikey->type; + break; + default: + *type = 0; + } +} static void print_item(struct scoutfs_segment_block *sblk, struct scoutfs_segment_item *item, u32 which, u32 off) @@ -269,19 +304,20 @@ static void print_item(struct scoutfs_segment_block *sblk, print_func_t printer; void *key; void *val; - __u8 type; + u8 type; + u8 zone; int i; key = (char *)&item->skip_links[item->nr_links]; val = (char *)key + le16_to_cpu(item->key_len); - type = *(__u8 *)key; - printer = type < array_size(printers) ? printers[type] : NULL; + find_zone_type(key, &zone, &type); + printer = find_printer(zone, type); - printf(" [%u]: type %u off %u key_len %u val_len %u nr_links %u flags %x%s\n", - which, type, off, le16_to_cpu(item->key_len), + printf(" [%u]: off %u key_len %u val_len %u nr_links %u flags %x%s\n", + which, off, le16_to_cpu(item->key_len), le16_to_cpu(item->val_len), item->nr_links, - item->flags, printer ? "" : " (unrecognized type)"); + item->flags, printer ? "" : " (unrecognized zone+type)"); printf(" links:"); for (i = 0; i < item->nr_links; i++) printf(" %u", le32_to_cpu(item->skip_links[i]));