mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-22 00:00:03 +03:00
Update bcachefs sources to ad72553649 bcachefs: Fix a null ptr deref
This commit is contained in:
parent
8b23ea867a
commit
5ee3f4d7b2
@ -1 +1 @@
|
||||
ac53c8857f8bb192ed59c0b3fab853760d56918d
|
||||
ad72553649c848bb907b294429d136f0069282b6
|
||||
|
@ -446,6 +446,13 @@ int bch2_alloc_read(struct bch_fs *c)
|
||||
|
||||
for_each_btree_key(&trans, iter, BTREE_ID_alloc, POS_MIN,
|
||||
BTREE_ITER_PREFETCH, k, ret) {
|
||||
/*
|
||||
* Not a fsck error because this is checked/repaired by
|
||||
* bch2_check_alloc_key() which runs later:
|
||||
*/
|
||||
if (!bch2_dev_bucket_exists(c, k.k->p))
|
||||
continue;
|
||||
|
||||
ca = bch_dev_bkey_exists(c, k.k->p.inode);
|
||||
bch2_alloc_to_v4(k, &a);
|
||||
|
||||
@ -614,7 +621,8 @@ static int bch2_check_alloc_key(struct btree_trans *trans,
|
||||
return ret;
|
||||
|
||||
if (fsck_err_on(!bch2_dev_bucket_exists(c, alloc_k.k->p), c,
|
||||
"alloc key for invalid device or bucket"))
|
||||
"alloc key for invalid device:bucket %llu:%llu",
|
||||
alloc_k.k->p.inode, alloc_k.k->p.offset))
|
||||
return bch2_btree_delete_at(trans, alloc_iter, 0);
|
||||
|
||||
ca = bch_dev_bkey_exists(c, alloc_k.k->p.inode);
|
||||
@ -706,7 +714,6 @@ static int bch2_check_discard_freespace_key(struct btree_trans *trans,
|
||||
struct bch_alloc_v4 a;
|
||||
u64 genbits;
|
||||
struct bpos pos;
|
||||
struct bkey_i *update;
|
||||
enum bch_data_type state = iter->btree_id == BTREE_ID_need_discard
|
||||
? BCH_DATA_need_discard
|
||||
: BCH_DATA_free;
|
||||
@ -728,9 +735,8 @@ static int bch2_check_discard_freespace_key(struct btree_trans *trans,
|
||||
bch2_trans_iter_init(trans, &alloc_iter, BTREE_ID_alloc, pos, 0);
|
||||
|
||||
if (fsck_err_on(!bch2_dev_bucket_exists(c, pos), c,
|
||||
"%llu:%llu set in %s btree but device or bucket does not exist",
|
||||
pos.inode, pos.offset,
|
||||
bch2_btree_ids[iter->btree_id]))
|
||||
"entry in %s btree for nonexistant dev:bucket %llu:%llu",
|
||||
bch2_btree_ids[iter->btree_id], pos.inode, pos.offset))
|
||||
goto delete;
|
||||
|
||||
k = bch2_btree_iter_peek_slot(&alloc_iter);
|
||||
@ -756,21 +762,8 @@ fsck_err:
|
||||
printbuf_exit(&buf);
|
||||
return ret;
|
||||
delete:
|
||||
if (iter->btree_id == BTREE_ID_freespace) {
|
||||
/* should probably add a helper for deleting extents */
|
||||
update = bch2_trans_kmalloc(trans, sizeof(*update));
|
||||
ret = PTR_ERR_OR_ZERO(update);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
bkey_init(&update->k);
|
||||
update->k.p = iter->pos;
|
||||
bch2_key_resize(&update->k, 1);
|
||||
|
||||
ret = bch2_trans_update(trans, iter, update, 0);
|
||||
} else {
|
||||
ret = bch2_btree_delete_at(trans, iter, 0);
|
||||
}
|
||||
ret = bch2_btree_delete_extent_at(trans, iter,
|
||||
iter->btree_id == BTREE_ID_freespace ? 1 : 0, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -847,10 +847,9 @@ struct bch_dirent {
|
||||
#define DT_SUBVOL 16
|
||||
#define BCH_DT_MAX 17
|
||||
|
||||
#define BCH_NAME_MAX (U8_MAX * sizeof(u64) - \
|
||||
#define BCH_NAME_MAX ((unsigned) (U8_MAX * sizeof(u64) - \
|
||||
sizeof(struct bkey) - \
|
||||
offsetof(struct bch_dirent, d_name))
|
||||
|
||||
offsetof(struct bch_dirent, d_name)))
|
||||
|
||||
/* Xattrs */
|
||||
|
||||
|
@ -105,7 +105,8 @@ static inline bool gc_visited(struct bch_fs *c, struct gc_pos pos)
|
||||
static inline void bch2_do_gc_gens(struct bch_fs *c)
|
||||
{
|
||||
atomic_inc(&c->kick_gc);
|
||||
wake_up_process(c->gc_thread);
|
||||
if (c->gc_thread)
|
||||
wake_up_process(c->gc_thread);
|
||||
}
|
||||
|
||||
#endif /* _BCACHEFS_BTREE_GC_H */
|
||||
|
@ -723,8 +723,8 @@ int bch2_fs_btree_key_cache_init(struct btree_key_cache *c)
|
||||
void bch2_btree_key_cache_to_text(struct printbuf *out, struct btree_key_cache *c)
|
||||
{
|
||||
pr_buf(out, "nr_freed:\t%zu\n", c->nr_freed);
|
||||
pr_buf(out, "nr_keys:\t%zu\n", atomic_long_read(&c->nr_keys));
|
||||
pr_buf(out, "nr_dirty:\t%zu\n", atomic_long_read(&c->nr_dirty));
|
||||
pr_buf(out, "nr_keys:\t%lu\n", atomic_long_read(&c->nr_keys));
|
||||
pr_buf(out, "nr_dirty:\t%lu\n", atomic_long_read(&c->nr_dirty));
|
||||
}
|
||||
|
||||
void bch2_btree_key_cache_exit(void)
|
||||
|
@ -51,6 +51,8 @@ enum btree_insert_flags {
|
||||
#define BCH_HASH_SET_MUST_CREATE (1 << __BCH_HASH_SET_MUST_CREATE)
|
||||
#define BCH_HASH_SET_MUST_REPLACE (1 << __BCH_HASH_SET_MUST_REPLACE)
|
||||
|
||||
int bch2_btree_delete_extent_at(struct btree_trans *, struct btree_iter *,
|
||||
unsigned, unsigned);
|
||||
int bch2_btree_delete_at(struct btree_trans *, struct btree_iter *, unsigned);
|
||||
|
||||
int __bch2_btree_insert(struct btree_trans *, enum btree_id, struct bkey_i *);
|
||||
|
@ -858,10 +858,11 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans,
|
||||
struct btree_insert_entry *i;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
int ret, u64s_delta = 0;
|
||||
int rw = (trans->flags & BTREE_INSERT_JOURNAL_REPLAY) ? READ : WRITE;
|
||||
|
||||
trans_for_each_update(trans, i) {
|
||||
if (bch2_bkey_invalid(c, bkey_i_to_s_c(i->k),
|
||||
i->bkey_type, WRITE, &buf)) {
|
||||
i->bkey_type, rw, &buf)) {
|
||||
printbuf_reset(&buf);
|
||||
pr_buf(&buf, "invalid bkey on insert from %s -> %ps",
|
||||
trans->fn, (void *) i->ip_allocated);
|
||||
@ -872,7 +873,7 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans,
|
||||
pr_newline(&buf);
|
||||
|
||||
bch2_bkey_invalid(c, bkey_i_to_s_c(i->k),
|
||||
i->bkey_type, WRITE, &buf);
|
||||
i->bkey_type, rw, &buf);
|
||||
|
||||
bch2_trans_inconsistent(trans, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
@ -1641,8 +1642,8 @@ int bch2_btree_insert(struct bch_fs *c, enum btree_id id,
|
||||
__bch2_btree_insert(&trans, id, k));
|
||||
}
|
||||
|
||||
int bch2_btree_delete_at(struct btree_trans *trans,
|
||||
struct btree_iter *iter, unsigned update_flags)
|
||||
int bch2_btree_delete_extent_at(struct btree_trans *trans, struct btree_iter *iter,
|
||||
unsigned len, unsigned update_flags)
|
||||
{
|
||||
struct bkey_i *k;
|
||||
|
||||
@ -1652,9 +1653,16 @@ int bch2_btree_delete_at(struct btree_trans *trans,
|
||||
|
||||
bkey_init(&k->k);
|
||||
k->k.p = iter->pos;
|
||||
bch2_key_resize(&k->k, len);
|
||||
return bch2_trans_update(trans, iter, k, update_flags);
|
||||
}
|
||||
|
||||
int bch2_btree_delete_at(struct btree_trans *trans,
|
||||
struct btree_iter *iter, unsigned update_flags)
|
||||
{
|
||||
return bch2_btree_delete_extent_at(trans, iter, 0, update_flags);
|
||||
}
|
||||
|
||||
int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id,
|
||||
struct bpos start, struct bpos end,
|
||||
unsigned update_flags,
|
||||
|
@ -108,7 +108,7 @@ int bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||
}
|
||||
|
||||
if (len > BCH_NAME_MAX) {
|
||||
pr_buf(err, "dirent name too big (%u > %lu)",
|
||||
pr_buf(err, "dirent name too big (%u > %u)",
|
||||
len, BCH_NAME_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -988,7 +988,7 @@ static void bch2_journal_read_device(struct closure *cl)
|
||||
for (i = 0; i < r->nr_ptrs; i++) {
|
||||
if (r->ptrs[i].dev == ca->dev_idx &&
|
||||
sector_to_bucket(ca, r->ptrs[i].sector) == ja->buckets[ja->cur_idx]) {
|
||||
unsigned wrote = (r->ptrs[i].sector % ca->mi.bucket_size) +
|
||||
unsigned wrote = bucket_remainder(ca, r->ptrs[i].sector) +
|
||||
vstruct_sectors(&r->j, c->block_bits);
|
||||
|
||||
ja->sectors_free = min(ja->sectors_free,
|
||||
|
@ -133,7 +133,7 @@ static int bch2_check_lru_key(struct btree_trans *trans,
|
||||
struct bch_alloc_v4 a;
|
||||
struct printbuf buf1 = PRINTBUF;
|
||||
struct printbuf buf2 = PRINTBUF;
|
||||
u64 idx;
|
||||
struct bpos alloc_pos;
|
||||
int ret;
|
||||
|
||||
lru_k = bch2_btree_iter_peek(lru_iter);
|
||||
@ -144,10 +144,15 @@ static int bch2_check_lru_key(struct btree_trans *trans,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
idx = le64_to_cpu(bkey_s_c_to_lru(lru_k).v->idx);
|
||||
alloc_pos = POS(lru_k.k->p.inode,
|
||||
le64_to_cpu(bkey_s_c_to_lru(lru_k).v->idx));
|
||||
|
||||
bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc,
|
||||
POS(lru_k.k->p.inode, idx), 0);
|
||||
if (fsck_err_on(!bch2_dev_bucket_exists(c, alloc_pos), c,
|
||||
"lru key points to nonexistent device:bucket %llu:%llu",
|
||||
alloc_pos.inode, alloc_pos.offset))
|
||||
return bch2_btree_delete_at(trans, lru_iter, 0);
|
||||
|
||||
bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, alloc_pos, 0);
|
||||
k = bch2_btree_iter_peek_slot(&iter);
|
||||
ret = bkey_err(k);
|
||||
if (ret)
|
||||
|
@ -138,8 +138,8 @@ static int walk_buckets_to_copygc(struct bch_fs *c)
|
||||
.dev = iter.pos.inode,
|
||||
.gen = a.gen,
|
||||
.replicas = 1 + a.stripe_redundancy,
|
||||
.fragmentation = (u64) a.dirty_sectors * (1ULL << 31)
|
||||
/ ca->mi.bucket_size,
|
||||
.fragmentation = div_u64((u64) a.dirty_sectors * (1ULL << 31),
|
||||
ca->mi.bucket_size),
|
||||
.sectors = a.dirty_sectors,
|
||||
.offset = bucket_to_sector(ca, iter.pos.offset),
|
||||
};
|
||||
|
@ -198,7 +198,7 @@ int bch2_journal_key_insert_take(struct bch_fs *c, enum btree_id id,
|
||||
if (keys->nr == keys->size) {
|
||||
struct journal_keys new_keys = {
|
||||
.nr = keys->nr,
|
||||
.size = max(keys->size, 8UL) * 2,
|
||||
.size = max_t(size_t, keys->size, 8) * 2,
|
||||
.journal_seq_base = keys->journal_seq_base,
|
||||
};
|
||||
|
||||
|
@ -1420,11 +1420,17 @@ static int bch2_dev_remove_alloc(struct bch_fs *c, struct bch_dev *ca)
|
||||
struct bpos end = POS(ca->dev_idx, U64_MAX);
|
||||
int ret;
|
||||
|
||||
ret = bch2_btree_delete_range(c, BTREE_ID_alloc, start, end,
|
||||
/*
|
||||
* We clear the LRU and need_discard btrees first so that we don't race
|
||||
* with bch2_do_invalidates() and bch2_do_discards()
|
||||
*/
|
||||
ret = bch2_btree_delete_range(c, BTREE_ID_lru, start, end,
|
||||
BTREE_TRIGGER_NORUN, NULL) ?:
|
||||
bch2_btree_delete_range(c, BTREE_ID_need_discard, start, end,
|
||||
BTREE_TRIGGER_NORUN, NULL) ?:
|
||||
bch2_btree_delete_range(c, BTREE_ID_freespace, start, end,
|
||||
BTREE_TRIGGER_NORUN, NULL) ?:
|
||||
bch2_btree_delete_range(c, BTREE_ID_need_discard, start, end,
|
||||
bch2_btree_delete_range(c, BTREE_ID_alloc, start, end,
|
||||
BTREE_TRIGGER_NORUN, NULL);
|
||||
if (ret)
|
||||
bch_err(c, "error %i removing dev alloc info", ret);
|
||||
@ -1459,19 +1465,19 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bch2_journal_flush_device_pins(&c->journal, ca->dev_idx);
|
||||
if (ret) {
|
||||
bch_err(ca, "Remove failed: error %i flushing journal", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bch2_dev_remove_alloc(c, ca);
|
||||
if (ret) {
|
||||
bch_err(ca, "Remove failed, error deleting alloc info");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bch2_journal_error(&c->journal);
|
||||
ret = bch2_journal_flush_device_pins(&c->journal, ca->dev_idx);
|
||||
if (ret) {
|
||||
bch_err(ca, "Remove failed: error %i flushing journal", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bch2_journal_flush(&c->journal);
|
||||
if (ret) {
|
||||
bch_err(ca, "Remove failed, journal error");
|
||||
goto err;
|
||||
|
Loading…
Reference in New Issue
Block a user