Commit 94932a08 authored by Alan Huang's avatar Alan Huang Committed by Kent Overstreet
Browse files

bcachefs: Refactor bch2_bset_fix_lookup_table



bch2_bset_fix_lookup_table is too complicated to be easily understood,
the comment "l now > where" there is also incorrect when where ==
t->end_offset. This patch therefore refactor the function, the idea is
that when where >= rw_aux_tree(b, t)[t->size - 1].offset, we don't need
to adjust the rw aux tree.

Signed-off-by: default avatarAlan Huang <mmpgouride@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent f1625637
Loading
Loading
Loading
Loading
+68 −60
Original line number Diff line number Diff line
@@ -885,6 +885,38 @@ struct bkey_packed *bch2_bkey_prev_filter(struct btree *b,

/* Insert */

static void rw_aux_tree_insert_entry(struct btree *b,
				     struct bset_tree *t,
				     unsigned idx)
{
	EBUG_ON(!idx || idx > t->size);
	struct bkey_packed *start = rw_aux_to_bkey(b, t, idx - 1);
	struct bkey_packed *end = idx < t->size
				  ? rw_aux_to_bkey(b, t, idx)
				  : btree_bkey_last(b, t);

	if (t->size < bset_rw_tree_capacity(b, t) &&
	    (void *) end - (void *) start > L1_CACHE_BYTES) {
		struct bkey_packed *k = start;

		while (1) {
			k = bkey_p_next(k);
			if (k == end)
				break;

			if ((void *) k - (void *) start >= L1_CACHE_BYTES) {
				memmove(&rw_aux_tree(b, t)[idx + 1],
					&rw_aux_tree(b, t)[idx],
					(void *) &rw_aux_tree(b, t)[t->size] -
					(void *) &rw_aux_tree(b, t)[idx]);
				t->size++;
				rw_aux_tree_set(b, t, idx, k);
				break;
			}
		}
	}
}

static void bch2_bset_fix_lookup_table(struct btree *b,
				       struct bset_tree *t,
				       struct bkey_packed *_where,
@@ -892,78 +924,54 @@ static void bch2_bset_fix_lookup_table(struct btree *b,
				       unsigned new_u64s)
{
	int shift = new_u64s - clobber_u64s;
	unsigned l, j, where = __btree_node_key_to_offset(b, _where);
	unsigned idx, j, where = __btree_node_key_to_offset(b, _where);

	EBUG_ON(bset_has_ro_aux_tree(t));

	if (!bset_has_rw_aux_tree(t))
		return;

	/* returns first entry >= where */
	l = rw_aux_tree_bsearch(b, t, where);

	if (!l) /* never delete first entry */
		l++;
	else if (l < t->size &&
		 where < t->end_offset &&
		 rw_aux_tree(b, t)[l].offset == where)
		rw_aux_tree_set(b, t, l++, _where);

	/* l now > where */
	if (where > rw_aux_tree(b, t)[t->size - 1].offset) {
		rw_aux_tree_insert_entry(b, t, t->size);
		goto verify;
	}

	for (j = l;
	     j < t->size &&
	     rw_aux_tree(b, t)[j].offset < where + clobber_u64s;
	     j++)
		;
	/* returns first entry >= where */
	idx = rw_aux_tree_bsearch(b, t, where);

	if (j < t->size &&
	    rw_aux_tree(b, t)[j].offset + shift ==
	    rw_aux_tree(b, t)[l - 1].offset)
		j++;
	if (rw_aux_tree(b, t)[idx].offset == where) {
		if (!idx) { /* never delete first entry */
			idx++;
		} else if (where < t->end_offset) {
			rw_aux_tree_set(b, t, idx++, _where);
		} else {
			EBUG_ON(where != t->end_offset);
			rw_aux_tree_insert_entry(b, t, --t->size);
			goto verify;
		}
	}

	memmove(&rw_aux_tree(b, t)[l],
		&rw_aux_tree(b, t)[j],
	EBUG_ON(idx < t->size && rw_aux_tree(b, t)[idx].offset <= where);
	if (idx < t->size &&
	    rw_aux_tree(b, t)[idx].offset + shift ==
	    rw_aux_tree(b, t)[idx - 1].offset) {
		memmove(&rw_aux_tree(b, t)[idx],
			&rw_aux_tree(b, t)[idx + 1],
			(void *) &rw_aux_tree(b, t)[t->size] -
		(void *) &rw_aux_tree(b, t)[j]);
	t->size -= j - l;
			(void *) &rw_aux_tree(b, t)[idx + 1]);
		t->size -= 1;
	}

	for (j = l; j < t->size; j++)
	for (j = idx; j < t->size; j++)
		rw_aux_tree(b, t)[j].offset += shift;

	EBUG_ON(l < t->size &&
		rw_aux_tree(b, t)[l].offset ==
		rw_aux_tree(b, t)[l - 1].offset);

	if (t->size < bset_rw_tree_capacity(b, t) &&
	    (l < t->size
	     ? rw_aux_tree(b, t)[l].offset
	     : t->end_offset) -
	    rw_aux_tree(b, t)[l - 1].offset >
	    L1_CACHE_BYTES / sizeof(u64)) {
		struct bkey_packed *start = rw_aux_to_bkey(b, t, l - 1);
		struct bkey_packed *end = l < t->size
			? rw_aux_to_bkey(b, t, l)
			: btree_bkey_last(b, t);
		struct bkey_packed *k = start;

		while (1) {
			k = bkey_p_next(k);
			if (k == end)
				break;
	EBUG_ON(idx < t->size &&
		rw_aux_tree(b, t)[idx].offset ==
		rw_aux_tree(b, t)[idx - 1].offset);

			if ((void *) k - (void *) start >= L1_CACHE_BYTES) {
				memmove(&rw_aux_tree(b, t)[l + 1],
					&rw_aux_tree(b, t)[l],
					(void *) &rw_aux_tree(b, t)[t->size] -
					(void *) &rw_aux_tree(b, t)[l]);
				t->size++;
				rw_aux_tree_set(b, t, l, k);
				break;
			}
		}
	}
	rw_aux_tree_insert_entry(b, t, idx);

verify:
	bch2_bset_verify_rw_aux_tree(b, t);
	bset_aux_tree_verify(b);
}