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

bcachefs: bch2_extent_drop_ptrs()

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1742237b
......@@ -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;
......
......@@ -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);
}
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);
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;
}
}
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)
......
......@@ -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 *);
......
......@@ -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;
......
......@@ -1067,14 +1067,19 @@ 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) {
ca = bch_dev_bkey_exists(c, ptr->dev);
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->journal.sectors_free -= sectors;
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;
}
replicas = bch2_extent_nr_ptrs(e.c);
......
......@@ -98,13 +98,9 @@ static int bch2_migrate_index_update(struct bch_write_op *op)
bch2_cut_back(new->k.p, &insert->k);
bch2_cut_back(insert->k.p, &new->k);
if (m->data_cmd == DATA_REWRITE) {
struct bch_extent_ptr *ptr = (void *)
bch2_extent_has_device(extent_i_to_s_c(insert),
m->data_opts.rewrite_dev);
BUG_ON(!ptr);
bch2_extent_drop_ptr(extent_i_to_s(insert), ptr);
}
if (m->data_cmd == DATA_REWRITE)
bch2_extent_drop_device(extent_i_to_s(insert),
m->data_opts.rewrite_dev);
extent_for_each_ptr_decode(extent_i_to_s(new), p, entry) {
if (bch2_extent_has_device(extent_i_to_s_c(insert), p.ptr.dev)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment