scoutfs: add option to force tiny btree blocks

Add a tunable option to force using tiny btree blocks on an active
mount.  This lets us quickly exercise large btrees.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-04-12 12:09:16 -07:00
committed by Zach Brown
parent e145267c05
commit c118f7cc03
4 changed files with 43 additions and 7 deletions

View File

@@ -26,6 +26,7 @@
#include "sort_priv.h"
#include "counters.h"
#include "triggers.h"
#include "options.h"
#include "scoutfs_trace.h"
@@ -184,9 +185,9 @@ static inline unsigned int all_len_bytes(unsigned key_len, unsigned val_len)
* 2 * min_used <= (bs - parent_min_free - hdr)
* min_used <= (bs - parent_min_free - hdr) / 2
*/
static inline unsigned int min_used_bytes(void)
static inline int min_used_bytes(int block_size)
{
return (SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_btree_block) -
return (block_size - sizeof(struct scoutfs_btree_block) -
SCOUTFS_BTREE_PARENT_MIN_FREE_BYTES) / 2;
}
@@ -852,7 +853,9 @@ static int try_split(struct super_block *sb, struct scoutfs_btree_root *root,
bool put_parent = false;
int ret;
if (right->level)
if (scoutfs_option_bool(sb, Opt_btree_force_tiny_blocks))
all_bytes = SCOUTFS_BLOCK_SIZE - SCOUTFS_BTREE_TINY_BLOCK_SIZE;
else if (right->level)
all_bytes = SCOUTFS_BTREE_PARENT_MIN_FREE_BYTES;
else
all_bytes = all_len_bytes(key_len, val_len);
@@ -913,12 +916,20 @@ static int try_merge(struct super_block *sb, struct scoutfs_btree_root *root,
struct scoutfs_btree_ring *bring = &SCOUTFS_SB(sb)->super.bring;
struct scoutfs_btree_block *sib;
struct scoutfs_btree_ref *ref;
unsigned int min_used;
unsigned int sib_pos;
bool move_right;
int to_move;
int ret;
if (used_total(bt) >= min_used_bytes())
BUILD_BUG_ON(min_used_bytes(SCOUTFS_BTREE_TINY_BLOCK_SIZE) < 0);
if (scoutfs_option_bool(sb, Opt_btree_force_tiny_blocks))
min_used = min_used_bytes(SCOUTFS_BTREE_TINY_BLOCK_SIZE);
else
min_used = min_used_bytes(SCOUTFS_BLOCK_SIZE);
if (used_total(bt) >= min_used)
return 0;
/* move items right into our block if we have a left sibling */
@@ -935,10 +946,10 @@ static int try_merge(struct super_block *sb, struct scoutfs_btree_root *root,
if (ret)
return ret;
if (used_total(sib) < min_used_bytes())
if (used_total(sib) < min_used)
to_move = used_total(sib);
else
to_move = min_used_bytes() - used_total(bt);
to_move = min_used - used_total(bt);
move_items(bt, sib, move_right, to_move);

View File

@@ -137,6 +137,14 @@ struct scoutfs_key_be {
sizeof(struct scoutfs_btree_item) + SCOUTFS_BTREE_MAX_KEY_LEN +\
sizeof(struct scoutfs_btree_ref))
/*
* When debugging we can tune the splitting and merging thresholds to
* create much larger trees by having blocks with many fewer items. We
* implement this by pretending the blocks are tiny. They're still
* large enough for a handful of items.
*/
#define SCOUTFS_BTREE_TINY_BLOCK_SIZE 512
/*
* A 4EB test image measured a worst case height of 17. This is plenty
* generous.

View File

@@ -34,12 +34,17 @@ static const match_table_t tokens = {
struct options_sb_info {
struct dentry *debugfs_dir;
u32 btree_force_tiny_blocks;
};
u32 scoutfs_option_u32(struct super_block *sb, int token)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct options_sb_info *osi = sbi->options;
switch(token) {
default: break;
case Opt_btree_force_tiny_blocks:
return osi->btree_force_tiny_blocks;
}
WARN_ON_ONCE(1);
@@ -109,6 +114,13 @@ int scoutfs_options_setup(struct super_block *sb)
goto out;
}
if (!debugfs_create_bool("btree_force_tiny_blocks", 0644,
osi->debugfs_dir,
&osi->btree_force_tiny_blocks)) {
ret = -ENOMEM;
goto out;
}
ret = 0;
out:
if (ret)

View File

@@ -7,6 +7,11 @@
enum {
Opt_listen = 0,
Opt_cluster,
/*
* For debugging we can quickly create huge trees by limiting
* the number of items in each block as though the blocks were tiny.
*/
Opt_btree_force_tiny_blocks,
Opt_err,
};