diff --git a/utils/src/format.h b/utils/src/format.h index 3c95f421..b435bfb7 100644 --- a/utils/src/format.h +++ b/utils/src/format.h @@ -252,8 +252,8 @@ struct scoutfs_segment_block { (SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE - SCOUTFS_INODE_INDEX_SIZE_TYPE + 1) /* node zone */ -#define SCOUTFS_FREE_EXTENT_BLKNO_TYPE 11 -#define SCOUTFS_FREE_EXTENT_BLOCKS_TYPE 12 +#define SCOUTFS_FREE_BITS_SEGNO_TYPE 1 +#define SCOUTFS_FREE_BITS_BLKNO_TYPE 2 /* fs zone */ #define SCOUTFS_INODE_TYPE 1 @@ -262,15 +262,11 @@ struct scoutfs_segment_block { #define SCOUTFS_READDIR_TYPE 4 #define SCOUTFS_LINK_BACKREF_TYPE 5 #define SCOUTFS_SYMLINK_TYPE 6 -#define SCOUTFS_FILE_EXTENT_TYPE 7 +#define SCOUTFS_BLOCK_MAPPING_TYPE 7 #define SCOUTFS_ORPHAN_TYPE 8 #define SCOUTFS_MAX_TYPE 16 /* power of 2 is efficient */ -/* 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 zone; @@ -303,38 +299,70 @@ struct scoutfs_link_backref_key { __u8 name[0]; } __packed; - -/* no value */ -struct scoutfs_file_extent_key { +/* key is bytes of encoded block mapping */ +struct scoutfs_block_mapping_key { __u8 zone; __be64 ino; __u8 type; - __be64 last_blk_off; - __be64 last_blkno; - __be64 blocks; - __u8 flags; + __be64 base; } __packed; -#define SCOUTFS_FILE_EXTENT_OFFLINE (1 << 0) +/* each mapping item describes a fixed number of blocks */ +#define SCOUTFS_BLOCK_MAPPING_SHIFT 6 +#define SCOUTFS_BLOCK_MAPPING_BLOCKS (1 << SCOUTFS_BLOCK_MAPPING_SHIFT) +#define SCOUTFS_BLOCK_MAPPING_MASK (SCOUTFS_BLOCK_MAPPING_BLOCKS - 1) -/* no value */ -struct scoutfs_free_extent_blkno_key { +/* + * The mapping item value is a byte stream that encodes the value of the + * mapped blocks. The first byte contains the last index that contains + * a mapped block in its low bits. The high bits contain the control + * bits for the first (and possibly only) mapped block. + * + * From then on we consume the control bits in the current control byte + * for each mapped block. Each block has two bits that describe the + * block: zero, incremental from previous block, delta encoded, and + * offline. If we run out of control bits then we consume the next byte + * in the stream for additional control bits. If we have a delta + * encoded block then we consume its encoded bytes from the byte stream. + */ + +#define SCOUTFS_BLOCK_ENC_ZERO 0 +#define SCOUTFS_BLOCK_ENC_INC 1 +#define SCOUTFS_BLOCK_ENC_DELTA 2 +#define SCOUTFS_BLOCK_ENC_OFFLINE 3 +#define SCOUTFS_BLOCK_ENC_MASK 3 + +#define SCOUTFS_ZIGZAG_MAX_BYTES (DIV_ROUND_UP(64, 7)) + +/* + * the largest block mapping has: nr byte, ctl bytes for all blocks, and + * worst case zigzag encodings for all blocks. + */ +#define SCOUTFS_BLOCK_MAPPING_MAX_BYTES \ + (1 + (SCOUTFS_BLOCK_MAPPING_BLOCKS / 4) + \ + (SCOUTFS_BLOCK_MAPPING_BLOCKS * SCOUTFS_ZIGZAG_MAX_BYTES)) + +/* free bit bitmaps contain a segment's worth of blocks */ +#define SCOUTFS_FREE_BITS_SHIFT \ + SCOUTFS_SEGMENT_BLOCK_SHIFT +#define SCOUTFS_FREE_BITS_BITS \ + (1 << SCOUTFS_FREE_BITS_SHIFT) +#define SCOUTFS_FREE_BITS_MASK \ + (SCOUTFS_FREE_BITS_BITS - 1) +#define SCOUTFS_FREE_BITS_U64S \ + DIV_ROUND_UP(SCOUTFS_FREE_BITS_BITS, 64) + +struct scoutfs_free_bits_key { __u8 zone; __be64 node_id; __u8 type; - __be64 last_blkno; - __be64 blocks; + __be64 base; } __packed; -struct scoutfs_free_extent_blocks_key { - __u8 zone; - __be64 node_id; - __u8 type; - __be64 blocks; - __be64 last_blkno; +struct scoutfs_free_bits { + __le64 bits[SCOUTFS_FREE_BITS_U64S]; } __packed; -/* no value */ struct scoutfs_orphan_key { __u8 zone; __be64 node_id; @@ -496,9 +524,7 @@ enum { #define SCOUTFS_MAX_KEY_SIZE \ offsetof(struct scoutfs_link_backref_key, name[SCOUTFS_NAME_LEN + 1]) -/* largest single val are dirents, larger broken up into units of this */ -#define SCOUTFS_MAX_VAL_SIZE \ - offsetof(struct scoutfs_dirent, name[SCOUTFS_NAME_LEN]) +#define SCOUTFS_MAX_VAL_SIZE SCOUTFS_BLOCK_MAPPING_MAX_BYTES #define SCOUTFS_XATTR_MAX_NAME_LEN 255 #define SCOUTFS_XATTR_MAX_SIZE 65536 @@ -510,7 +536,13 @@ enum { /* * structures used by dlm */ +#define SCOUTFS_LOCK_SCOPE_GLOBAL 1 +#define SCOUTFS_LOCK_SCOPE_FS_ITEMS 2 + +#define SCOUTFS_LOCK_TYPE_GLOBAL_RENAME 1 + struct scoutfs_lock_name { + __u8 scope; __u8 zone; __u8 type; __le64 first; @@ -572,6 +604,13 @@ struct scoutfs_net_segnos { __le64 segnos[0]; } __packed; +struct scoutfs_net_statfs { + __le64 total_segs; /* total segments in device */ + __le64 next_ino; /* next unused inode number */ + __le64 bfree; /* total free small blocks */ + __u8 uuid[SCOUTFS_UUID_BYTES]; /* logical volume uuid */ +} __packed; + /* XXX eventually we'll have net compaction and will need agents to agree */ /* one upper segment and fanout lower segments */ @@ -590,6 +629,7 @@ enum { SCOUTFS_NET_ADVANCE_SEQ, SCOUTFS_NET_GET_LAST_SEQ, SCOUTFS_NET_GET_MANIFEST_ROOT, + SCOUTFS_NET_STATFS, SCOUTFS_NET_UNKNOWN, }; diff --git a/utils/src/key.c b/utils/src/key.c index beff97b2..7588ea7f 100644 --- a/utils/src/key.c +++ b/utils/src/key.c @@ -197,22 +197,20 @@ static int pr_ino_idx(char *buf, struct scoutfs_key_buf *key, size_t size) be32_to_cpu(ikey->minor), be64_to_cpu(ikey->ino)); } -static int pr_free_ext(char *buf, struct scoutfs_key_buf *key, size_t size) +static int pr_free_bits(char *buf, struct scoutfs_key_buf *key, size_t size) { - 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", + [SCOUTFS_FREE_BITS_SEGNO_TYPE] = "fsg", + [SCOUTFS_FREE_BITS_BLKNO_TYPE] = "fbk", }; + struct scoutfs_free_bits_key *frk = key->data; return snprintf_key(buf, size, key, - sizeof(struct scoutfs_free_extent_blkno_key), 0, - "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)); + sizeof(struct scoutfs_block_mapping_key), 0, + "nod.%llu.%s.%llu", + be64_to_cpu(frk->node_id), + type_strings[frk->type], + be64_to_cpu(frk->base)); } static int pr_orphan(char *buf, struct scoutfs_key_buf *key, size_t size) @@ -292,18 +290,15 @@ static int pr_symlink(char *buf, struct scoutfs_key_buf *key, size_t size) be64_to_cpu(skey->ino)); } -static int pr_file_ext(char *buf, struct scoutfs_key_buf *key, size_t size) +static int pr_block_mapping(char *buf, struct scoutfs_key_buf *key, size_t size) { - struct scoutfs_file_extent_key *ekey = key->data; + struct scoutfs_block_mapping_key *bmk = key->data; return snprintf_key(buf, size, key, - sizeof(struct scoutfs_file_extent_key), 0, - "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), - be64_to_cpu(ekey->blocks), - ekey->flags); + sizeof(struct scoutfs_block_mapping_key), 0, + "fs.%llu.bmp.%llu", + be64_to_cpu(bmk->ino), + be64_to_cpu(bmk->base)); } const static key_printer_t key_printers[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = { @@ -313,8 +308,8 @@ const static key_printer_t key_printers[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = { pr_ino_idx, [SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = pr_ino_idx, - [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_EXTENT_BLKNO_TYPE] = pr_free_ext, - [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_EXTENT_BLOCKS_TYPE] = pr_free_ext, + [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_SEGNO_TYPE] = pr_free_bits, + [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_BLKNO_TYPE] = pr_free_bits, [SCOUTFS_NODE_ZONE][SCOUTFS_ORPHAN_TYPE] = pr_orphan, [SCOUTFS_FS_ZONE][SCOUTFS_INODE_TYPE] = pr_inode, [SCOUTFS_FS_ZONE][SCOUTFS_XATTR_TYPE] = pr_xattr, @@ -322,7 +317,7 @@ const static key_printer_t key_printers[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = { [SCOUTFS_FS_ZONE][SCOUTFS_READDIR_TYPE] = pr_readdir, [SCOUTFS_FS_ZONE][SCOUTFS_LINK_BACKREF_TYPE] = pr_link_backref, [SCOUTFS_FS_ZONE][SCOUTFS_SYMLINK_TYPE] = pr_symlink, - [SCOUTFS_FS_ZONE][SCOUTFS_FILE_EXTENT_TYPE] = pr_file_ext, + [SCOUTFS_FS_ZONE][SCOUTFS_BLOCK_MAPPING_TYPE] = pr_block_mapping, }; /* @@ -356,8 +351,8 @@ static int scoutfs_key_str_size(char *buf, struct scoutfs_key_buf *key, struct scoutfs_inode_index_key *ikey = key->data; type = ikey->type; } else if (zone == SCOUTFS_NODE_ZONE) { - struct scoutfs_free_extent_blkno_key *fkey = key->data; - type = fkey->type; + struct scoutfs_free_bits_key *fbk = key->data; + type = fbk->type; } else if (zone == SCOUTFS_FS_ZONE) { struct scoutfs_inode_key *ikey = key->data; type = ikey->type; diff --git a/utils/src/print.c b/utils/src/print.c index 08be009b..e5aba85b 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -190,48 +190,31 @@ static void print_symlink(void *key, int key_len, void *val, int val_len) } /* - * Just print the calculated starting blk_off/blkno, we can add a flag - * to print the raw values before the math if needed. + * XXX not decoding the bytes yet */ -static void print_file_extent(void *key, int key_len, void *val, int val_len) +static void print_block_mapping(void *key, int key_len, void *val, int val_len) { - struct scoutfs_file_extent_key *fext = key; - u64 blocks = be64_to_cpu(fext->blocks); - u64 blk_off = be64_to_cpu(fext->last_blk_off) - blocks + 1; - u64 blkno = be64_to_cpu(fext->last_blkno) - blocks + 1; + struct scoutfs_block_mapping_key *bmk = key; + u64 blk_off = be64_to_cpu(bmk->base) << SCOUTFS_BLOCK_MAPPING_SHIFT; + u8 nr = *((u8 *)val) & 63; - printf(" extent: ino %llu blk_off %llu blkno %llu blocks %llu " - "flags %x (%c)\n", - be64_to_cpu(fext->ino), blk_off, blkno, blocks, fext->flags, - (fext->flags & SCOUTFS_FILE_EXTENT_OFFLINE) ? 'O' : '-'); + printf(" block mapping: ino %llu blk_off %llu blocks %u\n", + be64_to_cpu(bmk->ino), blk_off, nr); } -static void print_free_extent(void *key, int key_len, void *val, int val_len) +static void print_free_bits(void *key, int key_len, void *val, int val_len) { - struct scoutfs_free_extent_blkno_key *blk = key; - struct scoutfs_free_extent_blocks_key *bks = key; - u64 last_blkno; - u64 node_id; - u64 blocks; - u64 blkno; - char *str; + struct scoutfs_free_bits_key *fbk = key; + struct scoutfs_free_bits *frb = val; + int i; - 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); - blocks = be64_to_cpu(blk->blocks); - } else { - str = "free (blocks)"; - node_id = be64_to_cpu(bks->node_id); - last_blkno = be64_to_cpu(bks->last_blkno); - blocks = be64_to_cpu(bks->blocks); - } + printf(" node_id %llx base %llu\n", + be64_to_cpu(fbk->node_id), be64_to_cpu(fbk->base)); - blkno = last_blkno - blocks + 1; - - printf(" %s: node_id %llx blkno %llu blocks %llu\n", - str, node_id, blkno, blocks); + printf(" bits:"); + for (i = 0; i < array_size(frb->bits); i++) + printf(" %016llx", le64_to_cpu(frb->bits[i])); + printf("\n"); } static void print_inode_index(void *key, int key_len, void *val, int val_len) @@ -253,9 +236,9 @@ static print_func_t find_printer(u8 zone, u8 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_FREE_BITS_SEGNO_TYPE || + type == SCOUTFS_FREE_BITS_BLKNO_TYPE) + return print_free_bits; if (type == SCOUTFS_ORPHAN_TYPE) return print_orphan; } @@ -268,7 +251,8 @@ static print_func_t find_printer(u8 zone, u8 type) 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; + case SCOUTFS_BLOCK_MAPPING_TYPE: + return print_block_mapping; } }