From 90de34361c6834e0a6ca1ea49f70cbdd1cdc5fef Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 11 Apr 2018 09:56:31 -0700 Subject: [PATCH] scoutfs: add trigger for advancing btree ring Add a trigger that lets us force advancing the btree block to the start of the next half. It's only safe to do this once migration has moved all the blocks out of the old half. Signed-off-by: Zach Brown --- kmod/src/btree.c | 44 ++++++++++++++++++++++++++++++++++++++++---- kmod/src/triggers.c | 1 + kmod/src/triggers.h | 1 + 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/kmod/src/btree.c b/kmod/src/btree.c index 9e5effd0..104b4e54 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -324,6 +324,25 @@ static bool first_block_in_half(struct scoutfs_btree_ring *bring) return block == 0 || block == (le64_to_cpu(bring->nr_blocks) / 2); } +/* Set next_block to the start of the other half */ +static void advance_to_next_half(struct scoutfs_btree_ring *bring) +{ + u64 block = le64_to_cpu(bring->next_block); + u64 half = le64_to_cpu(bring->nr_blocks) / 2; + u64 offset; + + if (block >= half) { + offset = le64_to_cpu(bring->nr_blocks) - block; + block = 0; + } else { + offset = half - block; + block = half; + } + + bring->next_block = cpu_to_le64(block); + le64_add_cpu(&bring->next_seq, offset); +} + static size_t super_root_offsets[] = { offsetof(struct scoutfs_super_block, alloc_root), offsetof(struct scoutfs_super_block, manifest.root), @@ -334,6 +353,19 @@ static size_t super_root_offsets[] = { (root = ((void *)super + super_root_offsets[i]), 1);\ i++) +static bool all_roots_migrated(struct scoutfs_super_block *super) +{ + struct scoutfs_btree_root *root; + int i; + + for_each_super_root(super, i, root) { + if (root->migration_key_len) + return false; + } + + return true; +} + static int cmp_hdr_item_key(void *priv, const void *a_ptr, const void *b_ptr) { struct scoutfs_btree_block *bt = priv; @@ -711,10 +743,16 @@ retry: bti->old_dirtied++; /* wrap next block and increase next seq */ + le64_add_cpu(&bring->next_block, 1); + le64_add_cpu(&bring->next_seq, 1); + if (le64_to_cpu(bring->next_block) == le64_to_cpu(bring->nr_blocks)) bring->next_block = 0; - else - le64_add_cpu(&bring->next_block, 1); + + /* advance to the next half when asked and migration made it safe */ + if (all_roots_migrated(super) && + scoutfs_trigger(sb, BTREE_ADVANCE_RING_HALF)) + advance_to_next_half(bring); /* reset the migration keys if we've just entered a new half */ if (first_block_in_half(bring)) { @@ -725,8 +763,6 @@ retry: } } - le64_add_cpu(&bring->next_seq, 1); - mutex_unlock(&bti->mutex); if (bt) { diff --git a/kmod/src/triggers.c b/kmod/src/triggers.c index 67cef0e6..a94f2b65 100644 --- a/kmod/src/triggers.c +++ b/kmod/src/triggers.c @@ -39,6 +39,7 @@ struct scoutfs_triggers { static char *names[] = { [SCOUTFS_TRIGGER_BTREE_STALE_READ] = "btree_stale_read", + [SCOUTFS_TRIGGER_BTREE_ADVANCE_RING_HALF] = "btree_advance_ring_half", [SCOUTFS_TRIGGER_HARD_STALE_ERROR] = "hard_stale_error", [SCOUTFS_TRIGGER_SEG_STALE_READ] = "seg_stale_read", [SCOUTFS_TRIGGER_STATFS_LOCK_PURGE] = "statfs_lock_purge", diff --git a/kmod/src/triggers.h b/kmod/src/triggers.h index 900e433f..d1fa9e71 100644 --- a/kmod/src/triggers.h +++ b/kmod/src/triggers.h @@ -3,6 +3,7 @@ enum { SCOUTFS_TRIGGER_BTREE_STALE_READ, + SCOUTFS_TRIGGER_BTREE_ADVANCE_RING_HALF, SCOUTFS_TRIGGER_HARD_STALE_ERROR, SCOUTFS_TRIGGER_SEG_STALE_READ, SCOUTFS_TRIGGER_STATFS_LOCK_PURGE,