summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-04-10 14:41:57 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-04-10 14:41:57 -0400
commit5ee3f4d7b29d6ee5a2173816892770d5b030bbc0 (patch)
tree8bd9160ef52bdfb63fa8e8f643817bf6477e8bfd
parent8b23ea867a45ead0e97c95a72c8fee40058c5b95 (diff)
Update bcachefs sources to ad72553649 bcachefs: Fix a null ptr derefv0.21
-rw-r--r--.bcachefs_revision2
-rw-r--r--libbcachefs/alloc_background.c33
-rw-r--r--libbcachefs/bcachefs_format.h5
-rw-r--r--libbcachefs/btree_gc.h3
-rw-r--r--libbcachefs/btree_key_cache.c4
-rw-r--r--libbcachefs/btree_update.h2
-rw-r--r--libbcachefs/btree_update_leaf.c16
-rw-r--r--libbcachefs/dirent.c2
-rw-r--r--libbcachefs/journal_io.c2
-rw-r--r--libbcachefs/lru.c13
-rw-r--r--libbcachefs/movinggc.c4
-rw-r--r--libbcachefs/recovery.c2
-rw-r--r--libbcachefs/super.c20
13 files changed, 61 insertions, 47 deletions
diff --git a/.bcachefs_revision b/.bcachefs_revision
index d9504b5e..10a1ce7d 100644
--- a/.bcachefs_revision
+++ b/.bcachefs_revision
@@ -1 +1 @@
-ac53c8857f8bb192ed59c0b3fab853760d56918d
+ad72553649c848bb907b294429d136f0069282b6
diff --git a/libbcachefs/alloc_background.c b/libbcachefs/alloc_background.c
index 03391464..4f208fab 100644
--- a/libbcachefs/alloc_background.c
+++ b/libbcachefs/alloc_background.c
@@ -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;
}
diff --git a/libbcachefs/bcachefs_format.h b/libbcachefs/bcachefs_format.h
index 498786ec..cc279abf 100644
--- a/libbcachefs/bcachefs_format.h
+++ b/libbcachefs/bcachefs_format.h
@@ -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 */
diff --git a/libbcachefs/btree_gc.h b/libbcachefs/btree_gc.h
index 8de54005..95d803b5 100644
--- a/libbcachefs/btree_gc.h
+++ b/libbcachefs/btree_gc.h
@@ -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 */
diff --git a/libbcachefs/btree_key_cache.c b/libbcachefs/btree_key_cache.c
index f5a942b6..ab394c2d 100644
--- a/libbcachefs/btree_key_cache.c
+++ b/libbcachefs/btree_key_cache.c
@@ -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)
diff --git a/libbcachefs/btree_update.h b/libbcachefs/btree_update.h
index ad13b073..a40f3460 100644
--- a/libbcachefs/btree_update.h
+++ b/libbcachefs/btree_update.h
@@ -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 *);
diff --git a/libbcachefs/btree_update_leaf.c b/libbcachefs/btree_update_leaf.c
index 4fb07b4c..fccfc0b3 100644
--- a/libbcachefs/btree_update_leaf.c
+++ b/libbcachefs/btree_update_leaf.c
@@ -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,
diff --git a/libbcachefs/dirent.c b/libbcachefs/dirent.c
index 28195988..716c8506 100644
--- a/libbcachefs/dirent.c
+++ b/libbcachefs/dirent.c
@@ -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;
}
diff --git a/libbcachefs/journal_io.c b/libbcachefs/journal_io.c
index f9d13e6a..871477dc 100644
--- a/libbcachefs/journal_io.c
+++ b/libbcachefs/journal_io.c
@@ -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,
diff --git a/libbcachefs/lru.c b/libbcachefs/lru.c
index 267f2f8f..ef4b4a9f 100644
--- a/libbcachefs/lru.c
+++ b/libbcachefs/lru.c
@@ -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)
diff --git a/libbcachefs/movinggc.c b/libbcachefs/movinggc.c
index 6d0d4049..99980c3d 100644
--- a/libbcachefs/movinggc.c
+++ b/libbcachefs/movinggc.c
@@ -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),
};
diff --git a/libbcachefs/recovery.c b/libbcachefs/recovery.c
index 9aa507c1..80befab8 100644
--- a/libbcachefs/recovery.c
+++ b/libbcachefs/recovery.c
@@ -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,
};
diff --git a/libbcachefs/super.c b/libbcachefs/super.c
index aba679c6..1401cb57 100644
--- a/libbcachefs/super.c
+++ b/libbcachefs/super.c
@@ -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);
+ ret = bch2_dev_remove_alloc(c, ca);
if (ret) {
- bch_err(ca, "Remove failed: error %i flushing journal", ret);
+ bch_err(ca, "Remove failed, error deleting alloc info");
goto err;
}
- ret = bch2_dev_remove_alloc(c, ca);
+ ret = bch2_journal_flush_device_pins(&c->journal, ca->dev_idx);
if (ret) {
- bch_err(ca, "Remove failed, error deleting alloc info");
+ bch_err(ca, "Remove failed: error %i flushing journal", ret);
goto err;
}
- ret = bch2_journal_error(&c->journal);
+ ret = bch2_journal_flush(&c->journal);
if (ret) {
bch_err(ca, "Remove failed, journal error");
goto err;