diff --git a/utils/src/format.h b/utils/src/format.h index 3093150b..9bc496b3 100644 --- a/utils/src/format.h +++ b/utils/src/format.h @@ -60,16 +60,23 @@ struct scoutfs_block_header { /* level 0 segments can have two full keys in the value :/ */ #define SCOUTFS_BTREE_MAX_VAL_LEN 768 +/* + * The min number of free bytes we must leave in a parent as we descend + * to modify. This leaves enough free bytes to insert a possibly maximal + * sized key as a seperator for a child block. Fewer bytes then this + * and split/merge might try to insert a max child item in the parent + * that wouldn't fit. + */ +#define SCOUTFS_BTREE_PARENT_MIN_FREE_BYTES \ + (sizeof(struct scoutfs_btree_item_header) + \ + sizeof(struct scoutfs_btree_item) + SCOUTFS_BTREE_MAX_KEY_LEN +\ + sizeof(struct scoutfs_btree_ref)) + /* * A 4EB test image measured a worst case height of 17. This is plenty * generous. */ #define SCOUTFS_BTREE_MAX_HEIGHT 20 - -/* btree blocks (beyond the first) need to be at least half full */ -#define SCOUTFS_BTREE_FREE_LIMIT \ - ((SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_btree_block)) / 2) - #define SCOUTFS_BTREE_BITS 8 /* diff --git a/utils/src/mkfs.c b/utils/src/mkfs.c index 943ffd8d..4a277c3b 100644 --- a/utils/src/mkfs.c +++ b/utils/src/mkfs.c @@ -68,13 +68,15 @@ static u64 calc_btree_blocks(u64 nr, u64 max_key, u64 max_val) item_bytes = sizeof(struct scoutfs_btree_item_header) + sizeof(struct scoutfs_btree_item) + max_key + sizeof(struct scoutfs_btree_ref); - fanout = (SCOUTFS_BLOCK_SIZE - SCOUTFS_BTREE_FREE_LIMIT) / item_bytes; + fanout = ((SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_btree_block) - + SCOUTFS_BTREE_PARENT_MIN_FREE_BYTES) / 2) / item_bytes; /* figure out how many items we have to store */ item_bytes = sizeof(struct scoutfs_btree_item_header) + sizeof(struct scoutfs_btree_item) + max_key + max_val; - block_items = (SCOUTFS_BLOCK_SIZE - SCOUTFS_BTREE_FREE_LIMIT) / item_bytes; + block_items = ((SCOUTFS_BLOCK_SIZE - + sizeof(struct scoutfs_btree_block)) / 2) / item_bytes; leaf_blocks = DIV_ROUND_UP(nr, block_items); /* then calc total blocks as we grow to have enough blocks for items */