mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
bcachefs: bch2_extent_drop_ptrs()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
1742237ba1
commit
a2753581f6
@ -1570,9 +1570,9 @@ retry:
|
||||
|
||||
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 @@ restart_narrow_pointers:
|
||||
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 @@ drop:
|
||||
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;
|
||||
struct bch_extent_ptr *ptr;
|
||||
|
||||
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++;
|
||||
|
||||
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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user