Commit a2753581 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet
Browse files

bcachefs: bch2_extent_drop_ptrs()

parent 1742237b
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1570,9 +1570,9 @@ static void bch2_btree_node_write_error(struct bch_fs *c,

	new_key = bkey_i_to_extent(&tmp.k);
	e = extent_i_to_s(new_key);
	extent_for_each_ptr_backwards(e, ptr)
		if (bch2_dev_list_has_dev(wbio->wbio.failed, ptr->dev))
			bch2_extent_drop_ptr(e, ptr);

	bch2_extent_drop_ptrs(e, ptr,
		bch2_dev_list_has_dev(wbio->wbio.failed, ptr->dev));

	if (!bch2_extent_nr_ptrs(e.c))
		goto err;
+33 −40
Original line number Diff line number Diff line
@@ -122,20 +122,11 @@ bch2_extent_has_device(struct bkey_s_c_extent e, unsigned dev)
	return NULL;
}

bool bch2_extent_drop_device(struct bkey_s_extent e, unsigned dev)
void bch2_extent_drop_device(struct bkey_s_extent e, unsigned dev)
{
	struct bch_extent_ptr *ptr;
	bool dropped = false;

	extent_for_each_ptr_backwards(e, ptr)
		if (ptr->dev == dev) {
			__bch2_extent_drop_ptr(e, ptr);
			dropped = true;
		}

	if (dropped)
		bch2_extent_drop_redundant_crcs(e);
	return dropped;
	bch2_extent_drop_ptrs(e, ptr, ptr->dev == dev);
}

const struct bch_extent_ptr *
@@ -267,21 +258,37 @@ bool bch2_extent_matches_ptr(struct bch_fs *c, struct bkey_s_c_extent e,
	return false;
}

/* Doesn't cleanup redundant crcs */
void __bch2_extent_drop_ptr(struct bkey_s_extent e, struct bch_extent_ptr *ptr)
union bch_extent_entry *bch2_extent_drop_ptr(struct bkey_s_extent e,
					     struct bch_extent_ptr *ptr)
{
	union bch_extent_entry *dst;
	union bch_extent_entry *src;

	EBUG_ON(ptr < &e.v->start->ptr ||
		ptr >= &extent_entry_last(e)->ptr);
	EBUG_ON(ptr->type != 1 << BCH_EXTENT_ENTRY_ptr);
	memmove_u64s_down(ptr, ptr + 1,
			  (u64 *) extent_entry_last(e) - (u64 *) (ptr + 1));
	e.k->u64s -= sizeof(*ptr) / sizeof(u64);

	src = to_entry(ptr + 1);

	if (src != extent_entry_last(e) &&
	    extent_entry_type(src) == BCH_EXTENT_ENTRY_ptr) {
		dst = to_entry(ptr);
	} else {
		extent_for_each_entry(e, dst) {
			if (dst == to_entry(ptr))
				break;

			if (extent_entry_next(dst) == to_entry(ptr) &&
			    extent_entry_is_crc(dst))
				break;
		}
	}

void bch2_extent_drop_ptr(struct bkey_s_extent e, struct bch_extent_ptr *ptr)
{
	__bch2_extent_drop_ptr(e, ptr);
	bch2_extent_drop_redundant_crcs(e);
	memmove_u64s_down(dst, src,
			  (u64 *) extent_entry_last(e) - (u64 *) src);
	e.k->u64s -= (u64 *) src - (u64 *) dst;

	return dst;
}

static inline bool can_narrow_crc(struct bch_extent_crc_unpacked u,
@@ -349,7 +356,7 @@ bool bch2_extent_narrow_crcs(struct bkey_i_extent *e,
		if (can_narrow_crc(p.crc, n)) {
			i->ptr.offset += p.crc.offset;
			extent_ptr_append(e, i->ptr);
			__bch2_extent_drop_ptr(extent_i_to_s(e), &i->ptr);
			bch2_extent_drop_ptr(extent_i_to_s(e), &i->ptr);
			goto restart_narrow_pointers;
		}

@@ -431,27 +438,13 @@ void bch2_extent_drop_redundant_crcs(struct bkey_s_extent e)
	EBUG_ON(bkey_val_u64s(e.k) && !bch2_extent_nr_ptrs(e.c));
}

static bool should_drop_ptr(const struct bch_fs *c,
			    struct bkey_s_c_extent e,
			    const struct bch_extent_ptr *ptr)
{
	return ptr->cached && ptr_stale(bch_dev_bkey_exists(c, ptr->dev), ptr);
}

static void bch2_extent_drop_stale(struct bch_fs *c, struct bkey_s_extent e)
{
	struct bch_extent_ptr *ptr = &e.v->start->ptr;
	bool dropped = false;

	while ((ptr = extent_ptr_next(e, ptr)))
		if (should_drop_ptr(c, e.c, ptr)) {
			__bch2_extent_drop_ptr(e, ptr);
			dropped = true;
		} else
			ptr++;
	struct bch_extent_ptr *ptr;

	if (dropped)
		bch2_extent_drop_redundant_crcs(e);
	bch2_extent_drop_ptrs(e, ptr,
		ptr->cached &&
		ptr_stale(bch_dev_bkey_exists(c, ptr->dev), ptr));
}

bool bch2_ptr_normalize(struct bch_fs *c, struct btree *b, struct bkey_s k)
+17 −26
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ void bch2_extent_mark_replicas_cached(struct bch_fs *, struct bkey_s_extent,

const struct bch_extent_ptr *
bch2_extent_has_device(struct bkey_s_c_extent, unsigned);
bool bch2_extent_drop_device(struct bkey_s_extent, unsigned);
void bch2_extent_drop_device(struct bkey_s_extent, unsigned);
const struct bch_extent_ptr *
bch2_extent_has_group(struct bch_fs *, struct bkey_s_c_extent, unsigned);
const struct bch_extent_ptr *
@@ -400,29 +400,6 @@ out: \

/* Iterate over pointers backwards: */

#define extent_ptr_prev(_e, _ptr)					\
({									\
	typeof(&(_e).v->start->ptr) _p;					\
	typeof(&(_e).v->start->ptr) _prev = NULL;			\
									\
	extent_for_each_ptr(_e, _p) {					\
		if (_p == (_ptr))					\
			break;						\
		_prev = _p;						\
	}								\
									\
	_prev;								\
})

/*
 * Use this when you'll be dropping pointers as you iterate. Quadratic,
 * unfortunately:
 */
#define extent_for_each_ptr_backwards(_e, _ptr)				\
	for ((_ptr) = extent_ptr_prev(_e, NULL);			\
	     (_ptr);							\
	     (_ptr) = extent_ptr_prev(_e, _ptr))

void bch2_extent_crc_append(struct bkey_i_extent *,
			    struct bch_extent_crc_unpacked);

@@ -517,8 +494,22 @@ bool bch2_can_narrow_extent_crcs(struct bkey_s_c_extent,
bool bch2_extent_narrow_crcs(struct bkey_i_extent *, struct bch_extent_crc_unpacked);
void bch2_extent_drop_redundant_crcs(struct bkey_s_extent);

void __bch2_extent_drop_ptr(struct bkey_s_extent, struct bch_extent_ptr *);
void bch2_extent_drop_ptr(struct bkey_s_extent, struct bch_extent_ptr *);
union bch_extent_entry *bch2_extent_drop_ptr(struct bkey_s_extent ,
					     struct bch_extent_ptr *);

#define bch2_extent_drop_ptrs(_e, _ptr, _cond)				\
do {									\
	_ptr = &(_e).v->start->ptr;					\
									\
	while ((_ptr = extent_ptr_next(e, _ptr))) {			\
		if (_cond) {						\
			_ptr = (void *) bch2_extent_drop_ptr(_e, _ptr);	\
			continue;					\
		}							\
									\
		(_ptr)++;						\
	}								\
} while (0)

bool bch2_cut_front(struct bpos, struct bkey_i *);
bool bch2_cut_back(struct bpos, struct bkey *);
+3 −3
Original line number Diff line number Diff line
@@ -327,9 +327,9 @@ static void __bch2_write_index(struct bch_write_op *op)
		bkey_copy(dst, src);

		e = bkey_i_to_s_extent(dst);
		extent_for_each_ptr_backwards(e, ptr)
			if (test_bit(ptr->dev, op->failed.d))
				bch2_extent_drop_ptr(e, ptr);

		bch2_extent_drop_ptrs(e, ptr,
			test_bit(ptr->dev, op->failed.d));

		if (!bch2_extent_nr_ptrs(e.c)) {
			ret = -EIO;
+12 −7
Original line number Diff line number Diff line
@@ -1067,13 +1067,18 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w,
	 * entry - that's why we drop pointers to devices <= current free space,
	 * i.e. whichever device was limiting the current journal entry size.
	 */
	extent_for_each_ptr_backwards(e, ptr) {
	bch2_extent_drop_ptrs(e, ptr, ({
		ca = bch_dev_bkey_exists(c, ptr->dev);

		if (ca->mi.state != BCH_MEMBER_STATE_RW ||
		    ca->journal.sectors_free <= sectors)
			__bch2_extent_drop_ptr(e, ptr);
		else
		ca->mi.state != BCH_MEMBER_STATE_RW ||
		ca->journal.sectors_free <= sectors;
	}));

	extent_for_each_ptr(e, ptr) {
		ca = bch_dev_bkey_exists(c, ptr->dev);

		BUG_ON(ca->mi.state != BCH_MEMBER_STATE_RW ||
		       ca->journal.sectors_free <= sectors);
		ca->journal.sectors_free -= sectors;
	}

Loading