diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-06-07 13:30:40 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2021-06-08 22:55:14 -0400 |
commit | 58ae103b0a2b5d881d6e8ff68fe17bb822148ce7 (patch) | |
tree | 4c794fc614fdf2d5e2521d335ef721b4c17f1d1e /libbcachefs | |
parent | f6d87e9a87859dbf9b15269d4de165cf3aadf661 (diff) |
Update bcachefs sources to e3a7cee503 bcachefs: Don't mark superblocks past end of usable space
Diffstat (limited to 'libbcachefs')
-rw-r--r-- | libbcachefs/acl.c | 2 | ||||
-rw-r--r-- | libbcachefs/alloc_background.c | 14 | ||||
-rw-r--r-- | libbcachefs/btree_cache.c | 5 | ||||
-rw-r--r-- | libbcachefs/btree_gc.c | 5 | ||||
-rw-r--r-- | libbcachefs/btree_iter.c | 141 | ||||
-rw-r--r-- | libbcachefs/btree_iter.h | 2 | ||||
-rw-r--r-- | libbcachefs/btree_types.h | 9 | ||||
-rw-r--r-- | libbcachefs/btree_update_interior.c | 24 | ||||
-rw-r--r-- | libbcachefs/btree_update_leaf.c | 61 | ||||
-rw-r--r-- | libbcachefs/buckets.c | 16 | ||||
-rw-r--r-- | libbcachefs/ec.c | 15 | ||||
-rw-r--r-- | libbcachefs/fs-io.c | 4 | ||||
-rw-r--r-- | libbcachefs/fs.c | 2 | ||||
-rw-r--r-- | libbcachefs/fsck.c | 17 | ||||
-rw-r--r-- | libbcachefs/inode.c | 10 | ||||
-rw-r--r-- | libbcachefs/io.c | 12 | ||||
-rw-r--r-- | libbcachefs/journal.c | 5 | ||||
-rw-r--r-- | libbcachefs/migrate.c | 5 | ||||
-rw-r--r-- | libbcachefs/move.c | 5 | ||||
-rw-r--r-- | libbcachefs/replicas.c | 2 | ||||
-rw-r--r-- | libbcachefs/str_hash.h | 14 | ||||
-rw-r--r-- | libbcachefs/super.c | 5 | ||||
-rw-r--r-- | libbcachefs/tests.c | 2 | ||||
-rw-r--r-- | libbcachefs/xattr.c | 2 |
24 files changed, 243 insertions, 136 deletions
diff --git a/libbcachefs/acl.c b/libbcachefs/acl.c index 0f2d743..594e1f1 100644 --- a/libbcachefs/acl.c +++ b/libbcachefs/acl.c @@ -383,7 +383,7 @@ int bch2_acl_chmod(struct btree_trans *trans, } new->k.p = iter->pos; - bch2_trans_update(trans, iter, &new->k_i, 0); + ret = bch2_trans_update(trans, iter, &new->k_i, 0); *new_acl = acl; acl = NULL; err: diff --git a/libbcachefs/alloc_background.c b/libbcachefs/alloc_background.c index da63473..2324b81 100644 --- a/libbcachefs/alloc_background.c +++ b/libbcachefs/alloc_background.c @@ -340,9 +340,9 @@ retry: return 0; bch2_alloc_pack(c, &a, new_u); - bch2_trans_update(trans, iter, &a.k, - BTREE_TRIGGER_NORUN); - ret = bch2_trans_commit(trans, NULL, NULL, + ret = bch2_trans_update(trans, iter, &a.k, + BTREE_TRIGGER_NORUN) ?: + bch2_trans_commit(trans, NULL, NULL, BTREE_INSERT_NOFAIL|flags); err: if (ret == -EINTR) @@ -726,7 +726,8 @@ static int bucket_invalidate_btree(struct btree_trans *trans, u.write_time = atomic64_read(&c->io_clock[WRITE].now); bch2_alloc_pack(c, a, u); - bch2_trans_update(trans, iter, &a->k, BTREE_TRIGGER_BUCKET_INVALIDATE); + ret = bch2_trans_update(trans, iter, &a->k, + BTREE_TRIGGER_BUCKET_INVALIDATE); err: bch2_trans_iter_put(trans, iter); return ret; @@ -836,6 +837,11 @@ static int bch2_invalidate_buckets(struct bch_fs *c, struct bch_dev *ca) while (!ret && !fifo_full(&ca->free_inc) && ca->alloc_heap.used) { + if (kthread_should_stop()) { + ret = 1; + break; + } + ret = bch2_invalidate_one_bucket(c, ca, &journal_seq, (!fifo_empty(&ca->free_inc) ? BTREE_INSERT_NOWAIT : 0)); diff --git a/libbcachefs/btree_cache.c b/libbcachefs/btree_cache.c index f6adbe8..013cf0b 100644 --- a/libbcachefs/btree_cache.c +++ b/libbcachefs/btree_cache.c @@ -807,7 +807,10 @@ lock_node: if (bch2_btree_node_relock(iter, level + 1)) goto retry; - trace_trans_restart_btree_node_reused(iter->trans->ip); + trace_trans_restart_btree_node_reused(iter->trans->ip, + trace_ip, + iter->btree_id, + &iter->real_pos); return ERR_PTR(-EINTR); } } diff --git a/libbcachefs/btree_gc.c b/libbcachefs/btree_gc.c index b03432c..ba560fb 100644 --- a/libbcachefs/btree_gc.c +++ b/libbcachefs/btree_gc.c @@ -1665,9 +1665,10 @@ static int bch2_gc_btree_gens(struct bch_fs *c, enum btree_id btree_id) bch2_bkey_buf_reassemble(&sk, c, k); bch2_extent_normalize(c, bkey_i_to_s(sk.k)); - bch2_trans_update(&trans, iter, sk.k, 0); - commit_err = bch2_trans_commit(&trans, NULL, NULL, + commit_err = + bch2_trans_update(&trans, iter, sk.k, 0) ?: + bch2_trans_commit(&trans, NULL, NULL, BTREE_INSERT_NOWAIT| BTREE_INSERT_NOFAIL); if (commit_err == -EINTR) { diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c index bdb068e..cd714dc 100644 --- a/libbcachefs/btree_iter.c +++ b/libbcachefs/btree_iter.c @@ -170,8 +170,8 @@ success: return true; } -static inline bool btree_iter_get_locks(struct btree_iter *iter, - bool upgrade, bool trace) +static inline bool btree_iter_get_locks(struct btree_iter *iter, bool upgrade, + unsigned long trace_ip) { unsigned l = iter->level; int fail_idx = -1; @@ -183,16 +183,17 @@ static inline bool btree_iter_get_locks(struct btree_iter *iter, if (!(upgrade ? bch2_btree_node_upgrade(iter, l) : bch2_btree_node_relock(iter, l))) { - if (trace) - (upgrade - ? trace_node_upgrade_fail - : trace_node_relock_fail)(l, iter->l[l].lock_seq, - is_btree_node(iter, l) - ? 0 - : (unsigned long) iter->l[l].b, - is_btree_node(iter, l) - ? iter->l[l].b->c.lock.state.seq - : 0); + (upgrade + ? trace_node_upgrade_fail + : trace_node_relock_fail)(iter->trans->ip, trace_ip, + iter->btree_id, &iter->real_pos, + l, iter->l[l].lock_seq, + is_btree_node(iter, l) + ? 0 + : (unsigned long) iter->l[l].b, + is_btree_node(iter, l) + ? iter->l[l].b->c.lock.state.seq + : 0); fail_idx = l; btree_iter_set_dirty(iter, BTREE_ITER_NEED_TRAVERSE); @@ -372,9 +373,9 @@ static inline void bch2_btree_iter_verify_locks(struct btree_iter *iter) {} #endif __flatten -bool bch2_btree_iter_relock(struct btree_iter *iter, bool trace) +static bool bch2_btree_iter_relock(struct btree_iter *iter, unsigned long trace_ip) { - return btree_iter_get_locks(iter, false, trace); + return btree_iter_get_locks(iter, false, trace_ip); } bool __bch2_btree_iter_upgrade(struct btree_iter *iter, @@ -386,7 +387,7 @@ bool __bch2_btree_iter_upgrade(struct btree_iter *iter, iter->locks_want = new_locks_want; - if (btree_iter_get_locks(iter, true, true)) + if (btree_iter_get_locks(iter, true, _THIS_IP_)) return true; /* @@ -414,7 +415,7 @@ bool __bch2_btree_iter_upgrade(struct btree_iter *iter, linked->btree_id == iter->btree_id && linked->locks_want < new_locks_want) { linked->locks_want = new_locks_want; - btree_iter_get_locks(linked, true, false); + btree_iter_get_locks(linked, true, _THIS_IP_); } return false; @@ -455,13 +456,22 @@ void bch2_trans_downgrade(struct btree_trans *trans) /* Btree transaction locking: */ +static inline bool btree_iter_should_be_locked(struct btree_trans *trans, + struct btree_iter *iter) +{ + return (iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT) || + iter->should_be_locked; +} + bool bch2_trans_relock(struct btree_trans *trans) { struct btree_iter *iter; trans_for_each_iter(trans, iter) - if (!bch2_btree_iter_relock(iter, true)) { - trace_trans_restart_relock(trans->ip); + if (!bch2_btree_iter_relock(iter, _RET_IP_) && + btree_iter_should_be_locked(trans, iter)) { + trace_trans_restart_relock(trans->ip, _RET_IP_, + iter->btree_id, &iter->real_pos); return false; } return true; @@ -829,7 +839,14 @@ static inline struct bkey_s_c __btree_iter_unpack(struct btree_iter *iter, ret = bkey_disassemble(l->b, k, u); - if (bch2_debug_check_bkeys) + /* + * XXX: bch2_btree_bset_insert_key() generates invalid keys when we + * overwrite extents - it sets k->type = KEY_TYPE_deleted on the key + * being overwritten but doesn't change k->size. But this is ok, because + * those keys are never written out, we just have to avoid a spurious + * assertion here: + */ + if (bch2_debug_check_bkeys && !bkey_deleted(ret.k)) bch2_bkey_debugcheck(iter->trans->c, l->b, ret); return ret; @@ -1175,7 +1192,8 @@ err: static int btree_iter_traverse_one(struct btree_iter *, unsigned long); -static int __btree_iter_traverse_all(struct btree_trans *trans, int ret) +static int __btree_iter_traverse_all(struct btree_trans *trans, int ret, + unsigned long trace_ip) { struct bch_fs *c = trans->c; struct btree_iter *iter; @@ -1192,7 +1210,7 @@ retry_all: relock_fail = false; trans_for_each_iter(trans, iter) { - if (!bch2_btree_iter_relock(iter, true)) + if (!bch2_btree_iter_relock(iter, _THIS_IP_)) relock_fail = true; sorted[nr_sorted++] = iter->idx; } @@ -1269,13 +1287,13 @@ out: trans->in_traverse_all = false; - trace_trans_traverse_all(trans->ip); + trace_trans_traverse_all(trans->ip, trace_ip); return ret; } int bch2_btree_iter_traverse_all(struct btree_trans *trans) { - return __btree_iter_traverse_all(trans, 0); + return __btree_iter_traverse_all(trans, 0, _RET_IP_); } static inline bool btree_iter_good_node(struct btree_iter *iter, @@ -1320,6 +1338,7 @@ static int btree_iter_traverse_one(struct btree_iter *iter, unsigned long trace_ip) { unsigned depth_want = iter->level; + int ret = 0; /* * if we need interior nodes locked, call btree_iter_relock() to make @@ -1327,16 +1346,18 @@ static int btree_iter_traverse_one(struct btree_iter *iter, */ if (iter->uptodate == BTREE_ITER_NEED_RELOCK || iter->locks_want > 1) - bch2_btree_iter_relock(iter, false); + bch2_btree_iter_relock(iter, _THIS_IP_); - if (btree_iter_type(iter) == BTREE_ITER_CACHED) - return bch2_btree_iter_traverse_cached(iter); + if (btree_iter_type(iter) == BTREE_ITER_CACHED) { + ret = bch2_btree_iter_traverse_cached(iter); + goto out; + } if (iter->uptodate < BTREE_ITER_NEED_RELOCK) - return 0; + goto out; if (unlikely(iter->level >= BTREE_MAX_DEPTH)) - return 0; + goto out; iter->level = btree_iter_up_until_good_node(iter, 0); @@ -1347,12 +1368,18 @@ static int btree_iter_traverse_one(struct btree_iter *iter, * btree_iter_lock_root() comes next and that it can't fail */ while (iter->level > depth_want) { - int ret = btree_iter_node(iter, iter->level) + ret = btree_iter_node(iter, iter->level) ? btree_iter_down(iter, trace_ip) : btree_iter_lock_root(iter, depth_want, trace_ip); if (unlikely(ret)) { - if (ret == 1) - return 0; + if (ret == 1) { + /* + * Got to the end of the btree (in + * BTREE_ITER_NODES mode) + */ + ret = 0; + goto out; + } iter->level = depth_want; @@ -1364,14 +1391,16 @@ static int btree_iter_traverse_one(struct btree_iter *iter, iter->l[iter->level].b = BTREE_ITER_NO_NODE_DOWN; } - return ret; + goto out; } } iter->uptodate = BTREE_ITER_NEED_PEEK; - +out: + trace_iter_traverse(iter->trans->ip, trace_ip, + iter->btree_id, &iter->real_pos, ret); bch2_btree_iter_verify(iter); - return 0; + return ret; } static int __must_check __bch2_btree_iter_traverse(struct btree_iter *iter) @@ -1382,7 +1411,7 @@ static int __must_check __bch2_btree_iter_traverse(struct btree_iter *iter) ret = bch2_trans_cond_resched(trans) ?: btree_iter_traverse_one(iter, _RET_IP_); if (unlikely(ret)) - ret = __btree_iter_traverse_all(trans, ret); + ret = __btree_iter_traverse_all(trans, ret, _RET_IP_); return ret; } @@ -1406,9 +1435,16 @@ btree_iter_traverse(struct btree_iter *iter) int __must_check bch2_btree_iter_traverse(struct btree_iter *iter) { + int ret; + btree_iter_set_search_pos(iter, btree_iter_search_key(iter)); - return btree_iter_traverse(iter); + ret = btree_iter_traverse(iter); + if (ret) + return ret; + + iter->should_be_locked = true; + return 0; } /* Iterate across nodes (leaf and interior nodes) */ @@ -1434,6 +1470,7 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) iter->pos = iter->real_pos = b->key.k.p; bch2_btree_iter_verify(iter); + iter->should_be_locked = true; return b; } @@ -1490,6 +1527,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) iter->pos = iter->real_pos = b->key.k.p; bch2_btree_iter_verify(iter); + iter->should_be_locked = true; return b; } @@ -1498,6 +1536,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) static void btree_iter_set_search_pos(struct btree_iter *iter, struct bpos new_pos) { + struct bpos old_pos = iter->real_pos; int cmp = bpos_cmp(new_pos, iter->real_pos); unsigned l = iter->level; @@ -1505,10 +1544,11 @@ static void btree_iter_set_search_pos(struct btree_iter *iter, struct bpos new_p goto out; iter->real_pos = new_pos; + iter->should_be_locked = false; if (unlikely(btree_iter_type(iter) == BTREE_ITER_CACHED)) { btree_node_unlock(iter, 0); - iter->l[0].b = BTREE_ITER_NO_NODE_UP; + iter->l[0].b = BTREE_ITER_NO_NODE_CACHED; btree_iter_set_dirty(iter, BTREE_ITER_NEED_TRAVERSE); return; } @@ -1537,6 +1577,11 @@ out: btree_iter_set_dirty(iter, BTREE_ITER_NEED_PEEK); bch2_btree_iter_verify(iter); +#ifdef CONFIG_BCACHEFS_DEBUG + trace_iter_set_search_pos(iter->trans->ip, _RET_IP_, + iter->btree_id, + &old_pos, &new_pos, l); +#endif } inline bool bch2_btree_iter_advance(struct btree_iter *iter) @@ -1659,6 +1704,7 @@ start: bch2_btree_iter_verify_entry_exit(iter); bch2_btree_iter_verify(iter); + iter->should_be_locked = true; return k; } @@ -1743,6 +1789,7 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter) out: bch2_btree_iter_verify_entry_exit(iter); bch2_btree_iter_verify(iter); + iter->should_be_locked = true; return k; no_key: /* @@ -1842,6 +1889,8 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) bch2_btree_iter_verify_entry_exit(iter); bch2_btree_iter_verify(iter); + iter->should_be_locked = true; + return k; } @@ -1879,6 +1928,8 @@ struct bkey_s_c bch2_btree_iter_peek_cached(struct btree_iter *iter) bkey_cmp(iter->pos, ck->key.pos)); BUG_ON(!ck->valid); + iter->should_be_locked = true; + return bkey_i_to_s_c(ck->k); } @@ -2055,13 +2106,6 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans, best = iter; } - trace_trans_get_iter(_RET_IP_, trans->ip, - btree_id, - &real_pos, locks_want, - best ? &best->real_pos : &pos_min, - best ? best->locks_want : 0, - best ? best->uptodate : BTREE_ITER_NEED_TRAVERSE); - if (!best) { iter = btree_trans_iter_alloc(trans); bch2_btree_iter_init(trans, iter, btree_id); @@ -2090,7 +2134,7 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans, locks_want = min(locks_want, BTREE_MAX_DEPTH); if (locks_want > iter->locks_want) { iter->locks_want = locks_want; - btree_iter_get_locks(iter, true, false); + btree_iter_get_locks(iter, true, _THIS_IP_); } while (iter->level != depth) { @@ -2108,6 +2152,13 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans, bch2_btree_iter_set_pos(iter, pos); btree_iter_set_search_pos(iter, real_pos); + trace_trans_get_iter(_RET_IP_, trans->ip, + btree_id, + &real_pos, locks_want, iter->uptodate, + best ? &best->real_pos : &pos_min, + best ? best->locks_want : U8_MAX, + best ? best->uptodate : U8_MAX); + return iter; } diff --git a/libbcachefs/btree_iter.h b/libbcachefs/btree_iter.h index 2f63adb..a2ce711 100644 --- a/libbcachefs/btree_iter.h +++ b/libbcachefs/btree_iter.h @@ -111,7 +111,6 @@ void bch2_btree_node_iter_fix(struct btree_iter *, struct btree *, struct btree_node_iter *, struct bkey_packed *, unsigned, unsigned); -bool bch2_btree_iter_relock(struct btree_iter *, bool); bool bch2_trans_relock(struct btree_trans *); void bch2_trans_unlock(struct btree_trans *); @@ -179,6 +178,7 @@ static inline void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos iter->k.p.offset = iter->pos.offset = new_pos.offset; iter->k.p.snapshot = iter->pos.snapshot = new_pos.snapshot; iter->k.size = 0; + iter->should_be_locked = false; } /* Sort order for locking btree iterators: */ diff --git a/libbcachefs/btree_types.h b/libbcachefs/btree_types.h index 06a2c41..bc0f482 100644 --- a/libbcachefs/btree_types.h +++ b/libbcachefs/btree_types.h @@ -230,6 +230,7 @@ enum btree_iter_uptodate { #define BTREE_ITER_NO_NODE_DOWN ((struct btree *) 5) #define BTREE_ITER_NO_NODE_INIT ((struct btree *) 6) #define BTREE_ITER_NO_NODE_ERROR ((struct btree *) 7) +#define BTREE_ITER_NO_NODE_CACHED ((struct btree *) 8) /* * @pos - iterator's current position @@ -251,7 +252,13 @@ struct btree_iter { u8 idx; enum btree_id btree_id:4; - enum btree_iter_uptodate uptodate:4; + enum btree_iter_uptodate uptodate:3; + /* + * True if we've returned a key (and thus are expected to keep it + * locked), false after set_pos - for avoiding spurious transaction + * restarts in bch2_trans_relock(): + */ + bool should_be_locked:1; unsigned level:4, min_depth:4, locks_want:4, diff --git a/libbcachefs/btree_update_interior.c b/libbcachefs/btree_update_interior.c index b0484c7..2d8093d 100644 --- a/libbcachefs/btree_update_interior.c +++ b/libbcachefs/btree_update_interior.c @@ -555,15 +555,15 @@ static void btree_update_nodes_written(struct btree_update *as) * on disk: */ for (i = 0; i < as->nr_old_nodes; i++) { - struct btree_node *bn = READ_ONCE(as->old_nodes[i]->data); + struct btree *old = as->old_nodes[i]; + __le64 seq; - /* - * This is technically a use after free, but it's just a read - - * but it might cause problems in userspace where freeing the - * buffer may unmap it: - */ - if (bn && bn->keys.seq == as->old_nodes_seq[i]) - btree_node_wait_on_io(as->old_nodes[i]); + six_lock_read(&old->c.lock, NULL, NULL); + seq = old->data ? old->data->keys.seq : 0; + six_unlock_read(&old->c.lock); + + if (seq == as->old_nodes_seq[i]) + btree_node_wait_on_io(old); } /* @@ -955,7 +955,9 @@ retry: * instead of locking/reserving all the way to the root: */ if (!bch2_btree_iter_upgrade(iter, U8_MAX)) { - trace_trans_restart_iter_upgrade(trans->ip); + trace_trans_restart_iter_upgrade(trans->ip, _RET_IP_, + iter->btree_id, + &iter->real_pos); return ERR_PTR(-EINTR); } @@ -996,7 +998,7 @@ retry: * closure argument */ if (flags & BTREE_INSERT_NOUNLOCK) { - trace_trans_restart_journal_preres_get(trans->ip); + trace_trans_restart_journal_preres_get(trans->ip, _RET_IP_); ret = -EINTR; goto err; } @@ -1012,7 +1014,7 @@ retry: BTREE_UPDATE_JOURNAL_RES, journal_flags); if (ret) { - trace_trans_restart_journal_preres_get(trans->ip); + trace_trans_restart_journal_preres_get(trans->ip, _RET_IP_); goto err; } diff --git a/libbcachefs/btree_update_leaf.c b/libbcachefs/btree_update_leaf.c index 70d2186..0d566be 100644 --- a/libbcachefs/btree_update_leaf.c +++ b/libbcachefs/btree_update_leaf.c @@ -228,7 +228,8 @@ static inline void btree_insert_entry_checks(struct btree_trans *trans, } static noinline int -bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned u64s) +bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned u64s, + unsigned long trace_ip) { struct bch_fs *c = trans->c; int ret; @@ -241,7 +242,7 @@ bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned u64s) return ret; if (!bch2_trans_relock(trans)) { - trace_trans_restart_journal_preres_get(trans->ip); + trace_trans_restart_journal_preres_get(trans->ip, trace_ip); return -EINTR; } @@ -368,7 +369,8 @@ static noinline void bch2_trans_mark_gc(struct btree_trans *trans) static inline int bch2_trans_commit_write_locked(struct btree_trans *trans, - struct btree_insert_entry **stopped_at) + struct btree_insert_entry **stopped_at, + unsigned long trace_ip) { struct bch_fs *c = trans->c; struct btree_insert_entry *i; @@ -378,7 +380,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, int ret; if (race_fault()) { - trace_trans_restart_fault_inject(trans->ip); + trace_trans_restart_fault_inject(trans->ip, trace_ip); return -EINTR; } @@ -525,7 +527,8 @@ static noinline int maybe_do_btree_merge(struct btree_trans *trans, struct btree * Get journal reservation, take write locks, and attempt to do btree update(s): */ static inline int do_bch2_trans_commit(struct btree_trans *trans, - struct btree_insert_entry **stopped_at) + struct btree_insert_entry **stopped_at, + unsigned long trace_ip) { struct bch_fs *c = trans->c; struct btree_insert_entry *i; @@ -559,7 +562,7 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, ? JOURNAL_RES_GET_RESERVED : 0)); if (unlikely(ret == -EAGAIN)) ret = bch2_trans_journal_preres_get_cold(trans, - trans->journal_preres_u64s); + trans->journal_preres_u64s, trace_ip); if (unlikely(ret)) return ret; @@ -578,7 +581,9 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, if (iter->nodes_locked != iter->nodes_intent_locked) { if (btree_iter_keep(trans, iter)) { if (!bch2_btree_iter_upgrade(iter, 1)) { - trace_trans_restart_upgrade(trans->ip); + trace_trans_restart_upgrade(trans->ip, trace_ip, + iter->btree_id, + &iter->real_pos); return -EINTR; } } else { @@ -606,7 +611,7 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, bch2_btree_node_lock_for_insert(c, iter_l(i->iter)->b, i->iter); - ret = bch2_trans_commit_write_locked(trans, stopped_at); + ret = bch2_trans_commit_write_locked(trans, stopped_at, trace_ip); trans_for_each_update2(trans, i) if (!same_leaf_as_prev(trans, i)) @@ -644,7 +649,7 @@ static int journal_reclaim_wait_done(struct bch_fs *c) static noinline int bch2_trans_commit_error(struct btree_trans *trans, struct btree_insert_entry *i, - int ret) + int ret, unsigned long trace_ip) { struct bch_fs *c = trans->c; unsigned flags = trans->flags; @@ -685,7 +690,9 @@ int bch2_trans_commit_error(struct btree_trans *trans, if (!ret || ret == -EINTR || (flags & BTREE_INSERT_NOUNLOCK)) { - trace_trans_restart_btree_node_split(trans->ip); + trace_trans_restart_btree_node_split(trans->ip, trace_ip, + i->iter->btree_id, + &i->iter->real_pos); ret = -EINTR; } break; @@ -703,7 +710,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, if (bch2_trans_relock(trans)) return 0; - trace_trans_restart_mark_replicas(trans->ip); + trace_trans_restart_mark_replicas(trans->ip, trace_ip); ret = -EINTR; break; case BTREE_INSERT_NEED_JOURNAL_RES: @@ -720,13 +727,13 @@ int bch2_trans_commit_error(struct btree_trans *trans, if (bch2_trans_relock(trans)) return 0; - trace_trans_restart_journal_res_get(trans->ip); + trace_trans_restart_journal_res_get(trans->ip, trace_ip); ret = -EINTR; break; case BTREE_INSERT_NEED_JOURNAL_RECLAIM: bch2_trans_unlock(trans); - trace_trans_blocked_journal_reclaim(trans->ip); + trace_trans_blocked_journal_reclaim(trans->ip, trace_ip); wait_event_freezable(c->journal.reclaim_wait, (ret = journal_reclaim_wait_done(c))); @@ -736,7 +743,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, if (bch2_trans_relock(trans)) return 0; - trace_trans_restart_journal_reclaim(trans->ip); + trace_trans_restart_journal_reclaim(trans->ip, trace_ip); ret = -EINTR; break; default: @@ -950,7 +957,9 @@ int __bch2_trans_commit(struct btree_trans *trans) i->trigger_flags); if (unlikely(ret)) { if (ret == -EINTR) - trace_trans_restart_mark(trans->ip); + trace_trans_restart_mark(trans->ip, _RET_IP_, + i->iter->btree_id, + &i->iter->pos); goto out; } } @@ -976,12 +985,16 @@ int __bch2_trans_commit(struct btree_trans *trans) trans_for_each_update2(trans, i) { ret = bch2_btree_iter_traverse(i->iter); if (unlikely(ret)) { - trace_trans_restart_traverse(trans->ip); + trace_trans_restart_traverse(trans->ip, _RET_IP_, + i->iter->btree_id, + &i->iter->pos); goto out; } if (unlikely(!bch2_btree_iter_upgrade(i->iter, i->level + 1))) { - trace_trans_restart_upgrade(trans->ip); + trace_trans_restart_upgrade(trans->ip, _RET_IP_, + i->iter->btree_id, + &i->iter->pos); ret = -EINTR; goto out; } @@ -997,7 +1010,7 @@ int __bch2_trans_commit(struct btree_trans *trans) retry: memset(&trans->journal_res, 0, sizeof(trans->journal_res)); - ret = do_bch2_trans_commit(trans, &i); + ret = do_bch2_trans_commit(trans, &i, _RET_IP_); /* make sure we didn't drop or screw up locks: */ bch2_btree_trans_verify_locks(trans); @@ -1023,7 +1036,7 @@ out_reset: return ret; err: - ret = bch2_trans_commit_error(trans, i, ret); + ret = bch2_trans_commit_error(trans, i, ret, _RET_IP_); if (ret) goto out; @@ -1198,9 +1211,9 @@ int bch2_btree_delete_at(struct btree_trans *trans, bkey_init(&k.k); k.k.p = iter->pos; - bch2_trans_update(trans, iter, &k, 0); - return bch2_trans_commit(trans, NULL, NULL, - BTREE_INSERT_NOFAIL|flags); + return bch2_trans_update(trans, iter, &k, 0) ?: + bch2_trans_commit(trans, NULL, NULL, + BTREE_INSERT_NOFAIL|flags); } int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id, @@ -1251,8 +1264,8 @@ retry: break; } - bch2_trans_update(trans, iter, &delete, 0); - ret = bch2_trans_commit(trans, NULL, journal_seq, + ret = bch2_trans_update(trans, iter, &delete, 0) ?: + bch2_trans_commit(trans, NULL, journal_seq, BTREE_INSERT_NOFAIL); if (ret) break; diff --git a/libbcachefs/buckets.c b/libbcachefs/buckets.c index d07085a..76d15a5 100644 --- a/libbcachefs/buckets.c +++ b/libbcachefs/buckets.c @@ -631,6 +631,12 @@ void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca, BUG_ON(type != BCH_DATA_sb && type != BCH_DATA_journal); + /* + * Backup superblock might be past the end of our normal usable space: + */ + if (b >= ca->mi.nbuckets) + return; + preempt_disable(); if (likely(c)) { @@ -1873,7 +1879,9 @@ static int __bch2_trans_mark_reflink_p(struct btree_trans *trans, } bch2_btree_iter_set_pos(iter, bkey_start_pos(k.k)); - bch2_trans_update(trans, iter, n, 0); + ret = bch2_trans_update(trans, iter, n, 0); + if (ret) + goto err; out: ret = sectors; err: @@ -2082,6 +2090,12 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans, }; int ret = 0; + /* + * Backup superblock might be past the end of our normal usable space: + */ + if (b >= ca->mi.nbuckets) + return 0; + a = bch2_trans_start_alloc_update(trans, &iter, &ptr, &u); if (IS_ERR(a)) return PTR_ERR(a); diff --git a/libbcachefs/ec.c b/libbcachefs/ec.c index fa7450d..db6e4f6 100644 --- a/libbcachefs/ec.c +++ b/libbcachefs/ec.c @@ -741,9 +741,8 @@ found_slot: stripe->k.p = iter->pos; - bch2_trans_update(&trans, iter, &stripe->k_i, 0); - - ret = bch2_trans_commit(&trans, res, NULL, + ret = bch2_trans_update(&trans, iter, &stripe->k_i, 0) ?: + bch2_trans_commit(&trans, res, NULL, BTREE_INSERT_NOFAIL); err: bch2_trans_iter_put(&trans, iter); @@ -791,7 +790,7 @@ static int ec_stripe_bkey_update(struct btree_trans *trans, stripe_blockcount_set(&new->v, i, stripe_blockcount_get(existing, i)); - bch2_trans_update(trans, iter, &new->k_i, 0); + ret = bch2_trans_update(trans, iter, &new->k_i, 0); err: bch2_trans_iter_put(trans, iter); return ret; @@ -864,9 +863,8 @@ static int ec_stripe_update_ptrs(struct bch_fs *c, extent_stripe_ptr_add(e, s, ec_ptr, block); bch2_btree_iter_set_pos(iter, bkey_start_pos(&sk.k->k)); - bch2_trans_update(&trans, iter, sk.k, 0); - - ret = bch2_trans_commit(&trans, NULL, NULL, + ret = bch2_trans_update(&trans, iter, sk.k, 0) ?: + bch2_trans_commit(&trans, NULL, NULL, BTREE_INSERT_NOFAIL); if (ret == -EINTR) ret = 0; @@ -1588,8 +1586,7 @@ write: stripe_blockcount_set(&new_key->v, i, m->block_sectors[i]); - bch2_trans_update(trans, iter, &new_key->k_i, 0); - return 0; + return bch2_trans_update(trans, iter, &new_key->k_i, 0); } int bch2_stripes_write(struct bch_fs *c, unsigned flags) diff --git a/libbcachefs/fs-io.c b/libbcachefs/fs-io.c index dc7916c..ef28995 100644 --- a/libbcachefs/fs-io.c +++ b/libbcachefs/fs-io.c @@ -2532,7 +2532,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode, } bch2_bkey_buf_init(©); - bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256); + bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024); src = bch2_trans_get_iter(&trans, BTREE_ID_extents, POS(inode->v.i_ino, src_start >> 9), BTREE_ITER_INTENT); @@ -2652,7 +2652,7 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode, unsigned replicas = io_opts(c, &inode->ei_inode).data_replicas; int ret = 0; - bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); + bch2_trans_init(&trans, c, BTREE_ITER_MAX, 512); iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, POS(inode->v.i_ino, start_sector), diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c index e8a329c..c567e17 100644 --- a/libbcachefs/fs.c +++ b/libbcachefs/fs.c @@ -144,7 +144,7 @@ int __must_check bch2_write_inode(struct bch_fs *c, struct bch_inode_unpacked inode_u; int ret; - bch2_trans_init(&trans, c, 0, 256); + bch2_trans_init(&trans, c, 0, 512); retry: bch2_trans_begin(&trans); diff --git a/libbcachefs/fsck.c b/libbcachefs/fsck.c index a40459d..89a130d 100644 --- a/libbcachefs/fsck.c +++ b/libbcachefs/fsck.c @@ -305,9 +305,8 @@ static int hash_redo_key(struct btree_trans *trans, bkey_init(&delete->k); delete->k.p = k_iter->pos; - bch2_trans_update(trans, k_iter, delete, 0); - - return bch2_hash_set(trans, desc, hash_info, k_iter->pos.inode, tmp, 0); + return bch2_trans_update(trans, k_iter, delete, 0) ?: + bch2_hash_set(trans, desc, hash_info, k_iter->pos.inode, tmp, 0); } static int fsck_hash_delete_at(struct btree_trans *trans, @@ -563,12 +562,12 @@ static int fix_overlapping_extent(struct btree_trans *trans, BTREE_ITER_INTENT|BTREE_ITER_NOT_EXTENTS); BUG_ON(iter->flags & BTREE_ITER_IS_EXTENTS); - bch2_trans_update(trans, iter, u, BTREE_TRIGGER_NORUN); + ret = bch2_trans_update(trans, iter, u, BTREE_TRIGGER_NORUN) ?: + bch2_trans_commit(trans, NULL, NULL, + BTREE_INSERT_NOFAIL| + BTREE_INSERT_LAZY_RW); bch2_trans_iter_put(trans, iter); - - return bch2_trans_commit(trans, NULL, NULL, - BTREE_INSERT_NOFAIL| - BTREE_INSERT_LAZY_RW); + return ret; } static int inode_backpointer_exists(struct btree_trans *trans, @@ -887,7 +886,7 @@ retry: ret = __bch2_trans_do(&trans, NULL, NULL, BTREE_INSERT_NOFAIL| BTREE_INSERT_LAZY_RW, - (bch2_trans_update(&trans, iter, &n->k_i, 0), 0)); + bch2_trans_update(&trans, iter, &n->k_i, 0)); kfree(n); if (ret) goto err; diff --git a/libbcachefs/inode.c b/libbcachefs/inode.c index 6b43a97..17d8eb5 100644 --- a/libbcachefs/inode.c +++ b/libbcachefs/inode.c @@ -333,8 +333,7 @@ int bch2_inode_write(struct btree_trans *trans, bch2_inode_pack(trans->c, inode_p, inode); inode_p->inode.k.p.snapshot = iter->snapshot; - bch2_trans_update(trans, iter, &inode_p->inode.k_i, 0); - return 0; + return bch2_trans_update(trans, iter, &inode_p->inode.k_i, 0); } const char *bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k) @@ -580,7 +579,7 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr, bool cached) struct bkey_s_c k; int ret; - bch2_trans_init(&trans, c, 0, 0); + bch2_trans_init(&trans, c, 0, 1024); /* * If this was a directory, there shouldn't be any real dirents left - @@ -629,9 +628,8 @@ retry: delete.k.p = iter->pos; delete.v.bi_generation = cpu_to_le32(inode_u.bi_generation + 1); - bch2_trans_update(&trans, iter, &delete.k_i, 0); - - ret = bch2_trans_commit(&trans, NULL, NULL, + ret = bch2_trans_update(&trans, iter, &delete.k_i, 0) ?: + bch2_trans_commit(&trans, NULL, NULL, BTREE_INSERT_NOFAIL); err: bch2_trans_iter_put(&trans, iter); diff --git a/libbcachefs/io.c b/libbcachefs/io.c index 157b2a0..ab37eff 100644 --- a/libbcachefs/io.c +++ b/libbcachefs/io.c @@ -301,8 +301,9 @@ int bch2_extent_update(struct btree_trans *trans, inode_iter = bch2_inode_peek(trans, &inode_u, k->k.p.inode, BTREE_ITER_INTENT); - if (IS_ERR(inode_iter)) - return PTR_ERR(inode_iter); + ret = PTR_ERR_OR_ZERO(inode_iter); + if (ret) + return ret; /* * XXX: @@ -329,11 +330,14 @@ int bch2_extent_update(struct btree_trans *trans, inode_p.inode.k.p.snapshot = iter->snapshot; - bch2_trans_update(trans, inode_iter, + ret = bch2_trans_update(trans, inode_iter, &inode_p.inode.k_i, 0); } bch2_trans_iter_put(trans, inode_iter); + + if (ret) + return ret; } ret = bch2_trans_update(trans, iter, k, 0) ?: @@ -1783,7 +1787,7 @@ static int __bch2_rbio_narrow_crcs(struct btree_trans *trans, if (!bch2_bkey_narrow_crcs(new, new_crc)) goto out; - bch2_trans_update(trans, iter, new, 0); + ret = bch2_trans_update(trans, iter, new, 0); out: bch2_trans_iter_put(trans, iter); return ret; diff --git a/libbcachefs/journal.c b/libbcachefs/journal.c index af5386d..d714779 100644 --- a/libbcachefs/journal.c +++ b/libbcachefs/journal.c @@ -807,8 +807,11 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, long b; if (new_fs) { + if (c) + percpu_down_read(&c->mark_lock); b = bch2_bucket_alloc_new_fs(ca); if (b < 0) { + percpu_up_read(&c->mark_lock); ret = -ENOSPC; goto err; } @@ -861,6 +864,8 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, ca->mi.bucket_size, gc_phase(GC_PHASE_SB), 0); + if (c) + percpu_up_read(&c->mark_lock); } else { ret = bch2_trans_do(c, NULL, NULL, BTREE_INSERT_NOFAIL, bch2_trans_mark_metadata_bucket(&trans, ca, diff --git a/libbcachefs/migrate.c b/libbcachefs/migrate.c index ef69a19..6ebe49b 100644 --- a/libbcachefs/migrate.c +++ b/libbcachefs/migrate.c @@ -73,9 +73,8 @@ static int __bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags bch2_btree_iter_set_pos(iter, bkey_start_pos(&sk.k->k)); - bch2_trans_update(&trans, iter, sk.k, 0); - - ret = bch2_trans_commit(&trans, NULL, NULL, + ret = bch2_trans_update(&trans, iter, sk.k, 0) ?: + bch2_trans_commit(&trans, NULL, NULL, BTREE_INSERT_NOFAIL); /* diff --git a/libbcachefs/move.c b/libbcachefs/move.c index 2fa763e..91be508 100644 --- a/libbcachefs/move.c +++ b/libbcachefs/move.c @@ -163,9 +163,8 @@ static int bch2_migrate_index_update(struct bch_write_op *op) goto out; } - bch2_trans_update(&trans, iter, insert, 0); - - ret = bch2_trans_commit(&trans, &op->res, + ret = bch2_trans_update(&trans, iter, insert, 0) ?: + bch2_trans_commit(&trans, &op->res, op_journal_seq(op), BTREE_INSERT_NOFAIL| m->data_opts.btree_insert_flags); diff --git a/libbcachefs/replicas.c b/libbcachefs/replicas.c index 8e6cccd..dbbbcc6 100644 --- a/libbcachefs/replicas.c +++ b/libbcachefs/replicas.c @@ -435,6 +435,8 @@ static int __bch2_mark_bkey_replicas(struct bch_fs *c, struct bkey_s_c k, unsigned i; int ret; + memset(&search, 0, sizeof(search)); + for (i = 0; i < cached.nr; i++) { bch2_replicas_entry_cached(&search.e, cached.devs[i]); diff --git a/libbcachefs/str_hash.h b/libbcachefs/str_hash.h index eab669a..2ff8e5b 100644 --- a/libbcachefs/str_hash.h +++ b/libbcachefs/str_hash.h @@ -281,7 +281,7 @@ not_found: swap(iter, slot); insert->k.p = iter->pos; - bch2_trans_update(trans, iter, insert, 0); + ret = bch2_trans_update(trans, iter, insert, 0); } goto out; @@ -296,20 +296,20 @@ int bch2_hash_delete_at(struct btree_trans *trans, struct bkey_i *delete; int ret; + delete = bch2_trans_kmalloc(trans, sizeof(*delete)); + ret = PTR_ERR_OR_ZERO(delete); + if (ret) + return ret; + ret = bch2_hash_needs_whiteout(trans, desc, info, iter); if (ret < 0) return ret; - delete = bch2_trans_kmalloc(trans, sizeof(*delete)); - if (IS_ERR(delete)) - return PTR_ERR(delete); - bkey_init(&delete->k); delete->k.p = iter->pos; delete->k.type = ret ? KEY_TYPE_hash_whiteout : KEY_TYPE_deleted; - bch2_trans_update(trans, iter, delete, 0); - return 0; + return bch2_trans_update(trans, iter, delete, 0); } static __always_inline diff --git a/libbcachefs/super.c b/libbcachefs/super.c index 4c67936..2a570eb 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -1826,6 +1826,11 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) goto err; } + ret = bch2_trans_mark_dev_sb(c, ca); + if (ret) { + goto err; + } + mutex_lock(&c->sb_lock); mi = &bch2_sb_get_members(c->disk_sb.sb)->members[ca->dev_idx]; mi->nbuckets = cpu_to_le64(nbuckets); diff --git a/libbcachefs/tests.c b/libbcachefs/tests.c index 254e3b3..63f4a83 100644 --- a/libbcachefs/tests.c +++ b/libbcachefs/tests.c @@ -621,7 +621,7 @@ static int __do_delete(struct btree_trans *trans, struct bpos pos) bkey_init(&delete.k); delete.k.p = k.k->p; - bch2_trans_update(trans, iter, &delete, 0); + ret = bch2_trans_update(trans, iter, &delete, 0); err: bch2_trans_iter_put(trans, iter); return ret; diff --git a/libbcachefs/xattr.c b/libbcachefs/xattr.c index 858aa87..e7b40b3 100644 --- a/libbcachefs/xattr.c +++ b/libbcachefs/xattr.c @@ -560,8 +560,10 @@ static const struct xattr_handler bch_xattr_bcachefs_effective_handler = { const struct xattr_handler *bch2_xattr_handlers[] = { &bch_xattr_user_handler, +#ifdef CONFIG_BCACHEFS_POSIX_ACL &posix_acl_access_xattr_handler, &posix_acl_default_xattr_handler, +#endif &bch_xattr_trusted_handler, &bch_xattr_security_handler, #ifndef NO_BCACHEFS_FS |