From e489658c490524a921bc30474fa54d55aa8867c4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 13 Oct 2021 11:00:02 -0400 Subject: [PATCH] Update bcachefs sources to 07c2895cb3 bcachefs: Add a valgrind memcheck hint --- .bcachefs_revision | 2 +- libbcachefs/btree_iter.c | 30 ++++++++++++--- libbcachefs/btree_update_interior.c | 9 +++++ libbcachefs/dirent.c | 27 ++----------- libbcachefs/fs-common.c | 52 +++++++++++++------------ libbcachefs/fsck.c | 23 ++--------- libbcachefs/migrate.c | 21 +++++----- libbcachefs/move.c | 22 +++++------ libbcachefs/subvolume.c | 59 +++++++++++++---------------- libbcachefs/subvolume.h | 2 + libbcachefs/super.c | 9 +++-- libbcachefs/util.c | 7 +++- libbcachefs/varint.c | 7 ++++ 13 files changed, 139 insertions(+), 131 deletions(-) diff --git a/.bcachefs_revision b/.bcachefs_revision index f8ad12e7..d1622d3d 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -4114ced1db465b8f4e7f4d6a78aa11416a9ab5d9 +07c2895cb3372c0e7b406ab13264de80c7ff19eb diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c index b5484d77..18d2733e 100644 --- a/libbcachefs/btree_iter.c +++ b/libbcachefs/btree_iter.c @@ -165,11 +165,20 @@ static bool bch2_btree_node_upgrade(struct btree_trans *trans, { struct btree *b = path->l[level].b; - EBUG_ON(btree_lock_want(path, level) != BTREE_NODE_INTENT_LOCKED); - if (!is_btree_node(path, level)) return false; + switch (btree_lock_want(path, level)) { + case BTREE_NODE_UNLOCKED: + BUG_ON(btree_node_locked(path, level)); + return true; + case BTREE_NODE_READ_LOCKED: + BUG_ON(btree_node_intent_locked(path, level)); + return bch2_btree_node_relock(trans, path, level); + case BTREE_NODE_INTENT_LOCKED: + break; + } + if (btree_node_intent_locked(path, level)) return true; @@ -364,7 +373,8 @@ static void bch2_btree_path_verify_locks(struct btree_path *path) unsigned l; if (!path->nodes_locked) { - BUG_ON(path->uptodate == BTREE_ITER_UPTODATE); + BUG_ON(path->uptodate == BTREE_ITER_UPTODATE && + btree_path_node(path, path->level)); return; } @@ -1351,7 +1361,8 @@ retry_all: EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx))); - if (path->nodes_locked) + if (path->nodes_locked || + !btree_path_node(path, path->level)) i++; } @@ -1866,13 +1877,14 @@ bch2_btree_iter_traverse(struct btree_iter *iter) struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) { + struct btree_trans *trans = iter->trans; struct btree *b = NULL; int ret; EBUG_ON(iter->path->cached); bch2_btree_iter_verify(iter); - ret = bch2_btree_path_traverse(iter->trans, iter->path, iter->flags); + ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); if (ret) goto out; @@ -1884,7 +1896,11 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) bkey_init(&iter->k); iter->k.p = iter->pos = b->key.k.p; + + iter->path = btree_path_set_pos(trans, iter->path, b->key.k.p, + iter->flags & BTREE_ITER_INTENT); iter->path->should_be_locked = true; + BUG_ON(iter->path->uptodate); out: bch2_btree_iter_verify_entry_exit(iter); bch2_btree_iter_verify(iter); @@ -1949,7 +1965,11 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) bkey_init(&iter->k); iter->k.p = iter->pos = b->key.k.p; + + iter->path = btree_path_set_pos(trans, iter->path, b->key.k.p, + iter->flags & BTREE_ITER_INTENT); iter->path->should_be_locked = true; + BUG_ON(iter->path->uptodate); out: bch2_btree_iter_verify_entry_exit(iter); bch2_btree_iter_verify(iter); diff --git a/libbcachefs/btree_update_interior.c b/libbcachefs/btree_update_interior.c index c54e6b46..98c05bb0 100644 --- a/libbcachefs/btree_update_interior.c +++ b/libbcachefs/btree_update_interior.c @@ -1945,9 +1945,16 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite { struct bch_fs *c = trans->c; struct btree *new_hash = NULL; + struct btree_path *path = iter->path; struct closure cl; int ret = 0; + if (!btree_node_intent_locked(path, b->c.level) && + !bch2_btree_path_upgrade(trans, path, b->c.level + 1)) { + btree_trans_restart(trans); + return -EINTR; + } + closure_init_stack(&cl); /* @@ -1966,8 +1973,10 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite new_hash = bch2_btree_node_mem_alloc(c); } + path->intent_ref++; ret = __bch2_btree_node_update_key(trans, iter, b, new_hash, new_key, skip_triggers); + --path->intent_ref; if (new_hash) { mutex_lock(&c->btree_cache.lock); diff --git a/libbcachefs/dirent.c b/libbcachefs/dirent.c index 8653a106..c7344ac8 100644 --- a/libbcachefs/dirent.c +++ b/libbcachefs/dirent.c @@ -191,34 +191,15 @@ int __bch2_dirent_read_target(struct btree_trans *trans, if (likely(d.v->d_type != DT_SUBVOL)) { *inum = le64_to_cpu(d.v->d_inum); } else { - struct btree_iter iter; - struct bkey_s_c k; - struct bkey_s_c_subvolume s; + struct bch_subvolume s; int ret; *subvol = le64_to_cpu(d.v->d_inum); - bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolumes, - POS(0, *subvol), - BTREE_ITER_CACHED); - k = bch2_btree_iter_peek_slot(&iter); - ret = bkey_err(k); - if (ret) - goto err; - if (k.k->type != KEY_TYPE_subvolume) { - ret = -ENOENT; - goto err; - } + ret = bch2_subvolume_get(trans, *subvol, !is_fsck, BTREE_ITER_CACHED, &s); - s = bkey_s_c_to_subvolume(k); - *snapshot = le32_to_cpu(s.v->snapshot); - *inum = le64_to_cpu(s.v->inode); -err: - if (ret == -ENOENT && !is_fsck) - bch2_fs_inconsistent(trans->c, "pointer to missing subvolume %u", - *subvol); - - bch2_trans_iter_exit(trans, &iter); + *snapshot = le32_to_cpu(s.snapshot); + *inum = le64_to_cpu(s.inode); } return ret; diff --git a/libbcachefs/fs-common.c b/libbcachefs/fs-common.c index 3e8e3c5b..c49de741 100644 --- a/libbcachefs/fs-common.c +++ b/libbcachefs/fs-common.c @@ -67,26 +67,14 @@ int bch2_create_trans(struct btree_trans *trans, if (!snapshot_src.inum) { /* Inode wasn't specified, just snapshot: */ - struct btree_iter subvol_iter; - struct bkey_s_c k; - - bch2_trans_iter_init(trans, &subvol_iter, BTREE_ID_subvolumes, - POS(0, snapshot_src.subvol), 0); - k = bch2_btree_iter_peek_slot(&subvol_iter); - - ret = bkey_err(k); - if (!ret && k.k->type != KEY_TYPE_subvolume) { - bch_err(c, "subvolume %u not found", - snapshot_src.subvol); - ret = -ENOENT; - } - - if (!ret) - snapshot_src.inum = le64_to_cpu(bkey_s_c_to_subvolume(k).v->inode); - bch2_trans_iter_exit(trans, &subvol_iter); + struct bch_subvolume s; + ret = bch2_subvolume_get(trans, snapshot_src.subvol, true, + BTREE_ITER_CACHED, &s); if (ret) goto err; + + snapshot_src.inum = le64_to_cpu(s.inode); } ret = bch2_inode_peek(trans, &inode_iter, new_inode, snapshot_src, @@ -279,18 +267,33 @@ int bch2_unlink_trans(struct btree_trans *trans, if (ret) goto err; - if (deleting_snapshot == 1 && !inode_u->bi_subvol) { - ret = -ENOENT; - goto err; - } - if (deleting_snapshot <= 0 && S_ISDIR(inode_u->bi_mode)) { ret = bch2_empty_dir_trans(trans, inum); if (ret) goto err; } - if (inode_u->bi_subvol) { + if (deleting_snapshot < 0 && + inode_u->bi_subvol) { + struct bch_subvolume s; + + ret = bch2_subvolume_get(trans, inode_u->bi_subvol, true, + BTREE_ITER_CACHED| + BTREE_ITER_WITH_UPDATES, + &s); + if (ret) + goto err; + + if (BCH_SUBVOLUME_SNAP(&s)) + deleting_snapshot = 1; + } + + if (deleting_snapshot == 1) { + if (!inode_u->bi_subvol) { + ret = -ENOENT; + goto err; + } + ret = bch2_subvolume_delete(trans, inode_u->bi_subvol, deleting_snapshot); if (ret) @@ -309,6 +312,8 @@ int bch2_unlink_trans(struct btree_trans *trans, ret = bch2_btree_iter_traverse(&dirent_iter); if (ret) goto err; + } else { + bch2_inode_nlink_dec(inode_u); } if (inode_u->bi_dir == dirent_iter.pos.inode && @@ -319,7 +324,6 @@ int bch2_unlink_trans(struct btree_trans *trans, dir_u->bi_mtime = dir_u->bi_ctime = inode_u->bi_ctime = now; dir_u->bi_nlink -= is_subdir_for_nlink(inode_u); - bch2_inode_nlink_dec(inode_u); ret = bch2_hash_delete_at(trans, bch2_dirent_hash_desc, &dir_hash, &dirent_iter, diff --git a/libbcachefs/fsck.c b/libbcachefs/fsck.c index 3622fb4d..208bf6df 100644 --- a/libbcachefs/fsck.c +++ b/libbcachefs/fsck.c @@ -103,29 +103,14 @@ static int snapshot_lookup_subvol(struct btree_trans *trans, u32 snapshot, static int __subvol_lookup(struct btree_trans *trans, u32 subvol, u32 *snapshot, u64 *inum) { - struct btree_iter iter; - struct bkey_s_c k; + struct bch_subvolume s; int ret; - bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolumes, - POS(0, subvol), 0); - k = bch2_btree_iter_peek_slot(&iter); - ret = bkey_err(k); - if (ret) - goto err; + ret = bch2_subvolume_get(trans, subvol, false, 0, &s); - if (k.k->type != KEY_TYPE_subvolume) { - bch_err(trans->c, "subvolume %u not fonud", subvol); - ret = -ENOENT; - goto err; - } - - *snapshot = le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot); - *inum = le64_to_cpu(bkey_s_c_to_subvolume(k).v->inode); -err: - bch2_trans_iter_exit(trans, &iter); + *snapshot = le32_to_cpu(s.snapshot); + *inum = le64_to_cpu(s.inode); return ret; - } static int subvol_lookup(struct btree_trans *trans, u32 subvol, diff --git a/libbcachefs/migrate.c b/libbcachefs/migrate.c index 7c764ee4..9f9eb799 100644 --- a/libbcachefs/migrate.c +++ b/libbcachefs/migrate.c @@ -51,7 +51,8 @@ static int __bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags BTREE_ITER_PREFETCH| BTREE_ITER_ALL_SNAPSHOTS); - while ((k = bch2_btree_iter_peek(&iter)).k && + while ((bch2_trans_begin(&trans), + (k = bch2_btree_iter_peek(&iter)).k) && !(ret = bkey_err(k))) { if (!bch2_bkey_has_device(k, dev_idx)) { bch2_btree_iter_advance(&iter); @@ -72,8 +73,6 @@ static int __bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags */ bch2_extent_normalize(c, bkey_i_to_s(sk.k)); - bch2_btree_iter_set_pos(&iter, bkey_start_pos(&sk.k->k)); - ret = bch2_btree_iter_traverse(&iter) ?: bch2_trans_update(&trans, &iter, sk.k, BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?: @@ -125,12 +124,14 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) closure_init_stack(&cl); for (id = 0; id < BTREE_ID_NR; id++) { - for_each_btree_node(&trans, iter, id, POS_MIN, - BTREE_ITER_PREFETCH, b) { -retry: + bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0, + BTREE_ITER_PREFETCH); + + while (bch2_trans_begin(&trans), + (b = bch2_btree_iter_peek_node(&iter))) { if (!bch2_bkey_has_device(bkey_i_to_s_c(&b->key), dev_idx)) - continue; + goto next; bch2_bkey_buf_copy(&k, c, &b->key); @@ -143,14 +144,16 @@ retry: ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, false); if (ret == -EINTR) { - b = bch2_btree_iter_peek_node(&iter); ret = 0; - goto retry; + continue; } + if (ret) { bch_err(c, "Error updating btree node key: %i", ret); break; } +next: + bch2_btree_iter_next_node(&iter); } bch2_trans_iter_exit(&trans, &iter); diff --git a/libbcachefs/move.c b/libbcachefs/move.c index 44a61818..0a8fe708 100644 --- a/libbcachefs/move.c +++ b/libbcachefs/move.c @@ -883,9 +883,11 @@ static int bch2_move_btree(struct bch_fs *c, id++) { stats->btree_id = id; - for_each_btree_node(&trans, iter, id, - id == start_btree_id ? start_pos : POS_MIN, - BTREE_ITER_PREFETCH, b) { + bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0, + BTREE_ITER_PREFETCH); + + while (bch2_trans_begin(&trans), + (b = bch2_btree_iter_peek_node(&iter))) { if (kthread && kthread_should_stop()) break; @@ -911,6 +913,7 @@ static int bch2_move_btree(struct bch_fs *c, b->data->keys.seq, 0) ?: ret; next: bch2_trans_cond_resched(&trans); + bch2_btree_iter_next_node(&iter); } bch2_trans_iter_exit(&trans, &iter); @@ -943,16 +946,9 @@ static enum data_cmd rereplicate_pred(struct bch_fs *c, void *arg, struct data_opts *data_opts) { unsigned nr_good = bch2_bkey_durability(c, k); - unsigned replicas = 0; - - switch (k.k->type) { - case KEY_TYPE_btree_ptr: - replicas = c->opts.metadata_replicas; - break; - case KEY_TYPE_extent: - replicas = io_opts->data_replicas; - break; - } + unsigned replicas = bkey_is_btree_ptr(k.k) + ? c->opts.metadata_replicas + : io_opts->data_replicas; if (!nr_good || nr_good >= replicas) return DATA_SKIP; diff --git a/libbcachefs/subvolume.c b/libbcachefs/subvolume.c index ff3b4d2d..d1c11105 100644 --- a/libbcachefs/subvolume.c +++ b/libbcachefs/subvolume.c @@ -89,23 +89,6 @@ int bch2_mark_snapshot(struct bch_fs *c, return 0; } -static int subvol_lookup(struct btree_trans *trans, unsigned id, struct bch_subvolume *s) -{ - struct btree_iter iter; - struct bkey_s_c k; - int ret; - - bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolumes, POS(0, id), 0); - k = bch2_btree_iter_peek_slot(&iter); - ret = bkey_err(k) ?: k.k->type == KEY_TYPE_subvolume ? 0 : -ENOENT; - - if (!ret) - *s = *bkey_s_c_to_subvolume(k).v; - - bch2_trans_iter_exit(trans, &iter); - return ret; -} - static int snapshot_lookup(struct btree_trans *trans, u32 id, struct bch_snapshot *s) { @@ -195,7 +178,7 @@ static int bch2_snapshot_check(struct btree_trans *trans, int ret; id = le32_to_cpu(s.v->subvol); - ret = lockrestart_do(trans, subvol_lookup(trans, id, &subvol)); + ret = lockrestart_do(trans, bch2_subvolume_get(trans, id, 0, false, &subvol)); if (ret == -ENOENT) bch_err(trans->c, "snapshot node %llu has nonexistent subvolume %u", s.k->p.offset, id); @@ -798,34 +781,44 @@ void bch2_subvolume_to_text(struct printbuf *out, struct bch_fs *c, le32_to_cpu(s.v->snapshot)); } -int bch2_subvolume_get_snapshot(struct btree_trans *trans, u32 subvol, - u32 *snapid) +int bch2_subvolume_get(struct btree_trans *trans, unsigned subvol, + bool inconsistent_if_not_found, + int iter_flags, + struct bch_subvolume *s) { struct btree_iter iter; struct bkey_s_c k; int ret; - bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolumes, - POS(0, subvol), - BTREE_ITER_CACHED| - BTREE_ITER_WITH_UPDATES); + bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolumes, POS(0, subvol), + iter_flags); k = bch2_btree_iter_peek_slot(&iter); - ret = bkey_err(k); - if (ret) - goto err; + ret = bkey_err(k) ?: k.k->type == KEY_TYPE_subvolume ? 0 : -ENOENT; - if (k.k->type != KEY_TYPE_subvolume) { + if (ret == -ENOENT && inconsistent_if_not_found) bch2_fs_inconsistent(trans->c, "missing subvolume %u", subvol); - ret = -EIO; - goto err; - } + if (!ret) + *s = *bkey_s_c_to_subvolume(k).v; - *snapid = le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot); -err: bch2_trans_iter_exit(trans, &iter); return ret; } +int bch2_subvolume_get_snapshot(struct btree_trans *trans, u32 subvol, + u32 *snapid) +{ + struct bch_subvolume s; + int ret; + + ret = bch2_subvolume_get(trans, subvol, true, + BTREE_ITER_CACHED| + BTREE_ITER_WITH_UPDATES, + &s); + + *snapid = le32_to_cpu(s.snapshot); + return ret; +} + /* XXX: mark snapshot id for deletion, walk btree and delete: */ int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid, int deleting_snapshot) diff --git a/libbcachefs/subvolume.h b/libbcachefs/subvolume.h index 0740c7b7..ed02b982 100644 --- a/libbcachefs/subvolume.h +++ b/libbcachefs/subvolume.h @@ -104,6 +104,8 @@ void bch2_subvolume_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c) .val_to_text = bch2_subvolume_to_text, \ } +int bch2_subvolume_get(struct btree_trans *, unsigned, + bool, int, struct bch_subvolume *); int bch2_subvolume_get_snapshot(struct btree_trans *, u32, u32 *); int bch2_subvolume_delete(struct btree_trans *, u32, int); diff --git a/libbcachefs/super.c b/libbcachefs/super.c index 1feb7dee..bb633e3d 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -1452,15 +1452,18 @@ static int bch2_dev_remove_alloc(struct bch_fs *c, struct bch_dev *ca) bch2_trans_init(&trans, c, 0, 0); for (i = 0; i < ca->mi.nbuckets; i++) { - ret = bch2_btree_key_cache_flush(&trans, - BTREE_ID_alloc, POS(ca->dev_idx, i)); + ret = lockrestart_do(&trans, + bch2_btree_key_cache_flush(&trans, + BTREE_ID_alloc, POS(ca->dev_idx, i))); if (ret) break; } bch2_trans_exit(&trans); - if (ret) + if (ret) { + bch_err(c, "error %i removing dev alloc info", ret); return ret; + } return bch2_btree_delete_range(c, BTREE_ID_alloc, POS(ca->dev_idx, 0), diff --git a/libbcachefs/util.c b/libbcachefs/util.c index 463260c0..9f21f68e 100644 --- a/libbcachefs/util.c +++ b/libbcachefs/util.c @@ -887,9 +887,14 @@ void eytzinger0_find_test(void) */ u64 *bch2_acc_percpu_u64s(u64 __percpu *p, unsigned nr) { - u64 *ret = this_cpu_ptr(p); + u64 *ret; int cpu; + /* access to pcpu vars has to be blocked by other locking */ + preempt_disable(); + ret = this_cpu_ptr(p); + preempt_enable(); + for_each_possible_cpu(cpu) { u64 *i = per_cpu_ptr(p, cpu); diff --git a/libbcachefs/varint.c b/libbcachefs/varint.c index 752179b2..a2d6bb71 100644 --- a/libbcachefs/varint.c +++ b/libbcachefs/varint.c @@ -4,6 +4,10 @@ #include #include +#ifdef CONFIG_VALGRIND +#include +#endif + #include "varint.h" /** @@ -95,6 +99,9 @@ int bch2_varint_encode_fast(u8 *out, u64 v) */ int bch2_varint_decode_fast(const u8 *in, const u8 *end, u64 *out) { +#ifdef CONFIG_VALGRIND + VALGRIND_MAKE_MEM_DEFINED(in, 8); +#endif u64 v = get_unaligned_le64(in); unsigned bytes = ffz(*in) + 1;