diff options
-rw-r--r-- | fs/bcachefs/alloc_background.c | 64 | ||||
-rw-r--r-- | fs/bcachefs/backpointers.c | 28 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs.h | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_cache.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/btree_cache.h | 8 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 35 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/btree_key_cache.c | 1 | ||||
-rw-r--r-- | fs/bcachefs/btree_types.h | 18 | ||||
-rw-r--r-- | fs/bcachefs/btree_update.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/btree_update.h | 50 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 18 | ||||
-rw-r--r-- | fs/bcachefs/dirent.c | 17 | ||||
-rw-r--r-- | fs/bcachefs/fsck.c | 47 | ||||
-rw-r--r-- | fs/bcachefs/inode.c | 7 | ||||
-rw-r--r-- | fs/bcachefs/io_misc.c | 14 | ||||
-rw-r--r-- | fs/bcachefs/logged_ops.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/namei.c | 15 | ||||
-rw-r--r-- | fs/bcachefs/sb-errors_format.h | 4 | ||||
-rw-r--r-- | fs/bcachefs/snapshot.c | 91 | ||||
-rw-r--r-- | fs/bcachefs/subvolume.c | 30 | ||||
-rw-r--r-- | fs/bcachefs/super-io.c | 37 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 1 |
25 files changed, 256 insertions, 257 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index 7db904c7a7e8..3fc728efbf5c 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -2104,44 +2104,46 @@ static int invalidate_one_bucket(struct btree_trans *trans, if (bch2_bucket_is_open_safe(c, bucket.inode, bucket.offset)) return 0; - CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, BTREE_ITER_cached); - struct bkey_s_c alloc_k = bch2_btree_iter_peek_slot(&alloc_iter); - ret = bkey_err(alloc_k); - if (ret) - return ret; + { + CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, BTREE_ITER_cached); + struct bkey_s_c alloc_k = bch2_btree_iter_peek_slot(&alloc_iter); + ret = bkey_err(alloc_k); + if (ret) + return ret; - struct bch_alloc_v4 a_convert; - const struct bch_alloc_v4 *a = bch2_alloc_to_v4(alloc_k, &a_convert); + struct bch_alloc_v4 a_convert; + const struct bch_alloc_v4 *a = bch2_alloc_to_v4(alloc_k, &a_convert); - /* We expect harmless races here due to the btree write buffer: */ - if (lru_pos_time(lru_iter->pos) != alloc_lru_idx_read(*a)) - return 0; + /* We expect harmless races here due to the btree write buffer: */ + if (lru_pos_time(lru_iter->pos) != alloc_lru_idx_read(*a)) + return 0; - /* - * Impossible since alloc_lru_idx_read() only returns nonzero if the - * bucket is supposed to be on the cached bucket LRU (i.e. - * BCH_DATA_cached) - * - * bch2_lru_validate() also disallows lru keys with lru_pos_time() == 0 - */ - BUG_ON(a->data_type != BCH_DATA_cached); - BUG_ON(a->dirty_sectors); + /* + * Impossible since alloc_lru_idx_read() only returns nonzero if the + * bucket is supposed to be on the cached bucket LRU (i.e. + * BCH_DATA_cached) + * + * bch2_lru_validate() also disallows lru keys with lru_pos_time() == 0 + */ + BUG_ON(a->data_type != BCH_DATA_cached); + BUG_ON(a->dirty_sectors); - if (!a->cached_sectors) { - bch2_check_bucket_backpointer_mismatch(trans, ca, bucket.offset, - true, last_flushed); - return 0; - } + if (!a->cached_sectors) { + bch2_check_bucket_backpointer_mismatch(trans, ca, bucket.offset, + true, last_flushed); + return 0; + } - unsigned cached_sectors = a->cached_sectors; - u8 gen = a->gen; + unsigned cached_sectors = a->cached_sectors; + u8 gen = a->gen; - ret = invalidate_one_bucket_by_bps(trans, ca, bucket, gen, last_flushed); - if (ret) - return ret; + ret = invalidate_one_bucket_by_bps(trans, ca, bucket, gen, last_flushed); + if (ret) + return ret; - trace_and_count(c, bucket_invalidate, c, bucket.inode, bucket.offset, cached_sectors); - --*nr_to_invalidate; + trace_and_count(c, bucket_invalidate, c, bucket.inode, bucket.offset, cached_sectors); + --*nr_to_invalidate; + } fsck_err: return ret; } diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 1aab9a63d0cb..45d3db41225a 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -395,22 +395,24 @@ static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, st return ret; } - CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, 0); - struct bkey_s_c alloc_k = bch2_btree_iter_peek_slot(&alloc_iter); - ret = bkey_err(alloc_k); - if (ret) - return ret; - - if (alloc_k.k->type != KEY_TYPE_alloc_v4) { - ret = bch2_backpointers_maybe_flush(trans, k, last_flushed); + { + CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, 0); + struct bkey_s_c alloc_k = bch2_btree_iter_peek_slot(&alloc_iter); + ret = bkey_err(alloc_k); if (ret) return ret; - if (fsck_err(trans, backpointer_to_missing_alloc, - "backpointer for nonexistent alloc key: %llu:%llu:0\n%s", - alloc_iter.pos.inode, alloc_iter.pos.offset, - (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - ret = bch2_backpointer_del(trans, k.k->p); + if (alloc_k.k->type != KEY_TYPE_alloc_v4) { + ret = bch2_backpointers_maybe_flush(trans, k, last_flushed); + if (ret) + return ret; + + if (fsck_err(trans, backpointer_to_missing_alloc, + "backpointer for nonexistent alloc key: %llu:%llu:0\n%s", + alloc_iter.pos.inode, alloc_iter.pos.offset, + (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) + ret = bch2_backpointer_del(trans, k.k->p); + } } fsck_err: return ret; diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 45c15bdaa6f4..cdf593c59922 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -845,8 +845,8 @@ struct bch_fs { unsigned long errors_silent[BITS_TO_LONGS(BCH_FSCK_ERR_MAX)]; u64 btrees_lost_data; } sb; - DARRAY(enum bcachefs_metadata_version) - incompat_versions_requested; + + unsigned long incompat_versions_requested[BITS_TO_LONGS(BCH_VERSION_MINOR(bcachefs_metadata_version_current))]; struct unicode_map *cf_encoding; diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index 2f7c384a8c81..8716eedd43fc 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -214,7 +214,7 @@ void bch2_node_pin(struct bch_fs *c, struct btree *b) struct btree_cache *bc = &c->btree_cache; guard(mutex)(&bc->lock); - if (b != btree_node_root(c, b) && !btree_node_pinned(b)) { + if (!btree_node_is_root(c, b) && !btree_node_pinned(b)) { set_btree_node_pinned(b); list_move(&b->list, &bc->live[1].list); bc->live[0].nr--; diff --git a/fs/bcachefs/btree_cache.h b/fs/bcachefs/btree_cache.h index 649e9dfd178a..035b2cb25077 100644 --- a/fs/bcachefs/btree_cache.h +++ b/fs/bcachefs/btree_cache.h @@ -144,6 +144,14 @@ static inline struct btree *btree_node_root(struct bch_fs *c, struct btree *b) return r ? r->b : NULL; } +static inline bool btree_node_is_root(struct bch_fs *c, struct btree *b) +{ + struct btree *root = btree_node_root(c, b); + + BUG_ON(b != root && b->c.level >= root->c.level); + return b == root; +} + const char *bch2_btree_id_str(enum btree_id); /* avoid */ void bch2_btree_id_to_text(struct printbuf *, enum btree_id); void bch2_btree_id_level_to_text(struct printbuf *, enum btree_id, unsigned); diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index ce3c7750a922..e27536d315b1 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -282,6 +282,38 @@ fsck_err: return ret; } +static int btree_check_root_boundaries(struct btree_trans *trans, struct btree *b) +{ + struct bch_fs *c = trans->c; + struct printbuf buf = PRINTBUF; + int ret = 0; + + BUG_ON(b->key.k.type == KEY_TYPE_btree_ptr_v2 && + !bpos_eq(bkey_i_to_btree_ptr_v2(&b->key)->v.min_key, + b->data->min_key)); + + if (mustfix_fsck_err_on(!bpos_eq(b->data->min_key, POS_MIN), + trans, btree_node_topology_bad_root_min_key, + "btree root with incorrect min_key%s", buf.buf)) { + ret = set_node_min(c, b, POS_MIN); + if (ret) + goto err; + } + + if (mustfix_fsck_err_on(!bpos_eq(b->data->max_key, SPOS_MAX), + trans, btree_node_topology_bad_root_max_key, + "btree root with incorrect min_key%s", buf.buf)) { + ret = set_node_max(c, b, SPOS_MAX); + if (ret) + goto err; + } + +err: +fsck_err: + printbuf_exit(&buf); + return ret; +} + static int btree_repair_node_end(struct btree_trans *trans, struct btree *b, struct btree *child, struct bpos *pulled_from_scan) { @@ -586,7 +618,8 @@ recover: struct btree *b = r->b; btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read); - ret = bch2_btree_repair_topology_recurse(trans, b, &pulled_from_scan); + ret = btree_check_root_boundaries(trans, b) ?: + bch2_btree_repair_topology_recurse(trans, b, &pulled_from_scan); six_unlock_read(&b->c.lock); if (bch2_err_matches(ret, BCH_ERR_topology_repair_drop_this_node)) { diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index ff580f76a641..a67babf69d39 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -2451,7 +2451,7 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en } if (bkey_whiteout(k.k) && - !(iter->flags & BTREE_ITER_key_cache_fill)) { + !(iter->flags & BTREE_ITER_nofilter_whiteouts)) { search_key = bkey_successor(iter, k.k->p); continue; } @@ -2867,7 +2867,7 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) if (unlikely(k.k->type == KEY_TYPE_whiteout && (iter->flags & BTREE_ITER_filter_snapshots) && - !(iter->flags & BTREE_ITER_key_cache_fill))) + !(iter->flags & BTREE_ITER_nofilter_whiteouts))) iter->k.type = KEY_TYPE_deleted; } else { struct bpos next; diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index a7c2087bc4a1..b117cb5d7f94 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -673,7 +673,7 @@ static inline struct bkey_s_c __bch2_bkey_get_typed(struct btree_iter *iter, { struct bkey_s_c k = bch2_btree_iter_peek_slot(iter); - if (!bkey_err(k) && k.k->type != type) + if (!bkey_err(k) && type && k.k->type != type) k = bkey_s_c_err(bch_err_throw(iter->trans->c, ENOENT_bkey_type_mismatch)); return k; } diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index 72c803f7b8d1..4890cbc88e7c 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -325,6 +325,7 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans, CLASS(btree_iter, iter)(trans, ck_path->btree_id, ck_path->pos, BTREE_ITER_intent| + BTREE_ITER_nofilter_whiteouts| BTREE_ITER_key_cache_fill| BTREE_ITER_cached_nofill); iter.flags &= ~BTREE_ITER_with_journal; diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index ffa250008d91..e893eb938bb3 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -229,6 +229,7 @@ struct btree_node_iter { x(snapshot_field) \ x(all_snapshots) \ x(filter_snapshots) \ + x(nofilter_whiteouts) \ x(nopreserve) \ x(cached_nofill) \ x(key_cache_fill) \ @@ -839,15 +840,15 @@ static inline bool btree_node_type_has_triggers(enum btree_node_type type) return BIT_ULL(type) & BTREE_NODE_TYPE_HAS_TRIGGERS; } -static inline bool btree_id_is_extents(enum btree_id btree) -{ - const u64 mask = 0 +static const u64 btree_is_extents_mask = 0 #define x(name, nr, flags, ...) |((!!((flags) & BTREE_IS_extents)) << nr) - BCH_BTREE_IDS() +BCH_BTREE_IDS() #undef x - ; +; - return BIT_ULL(btree) & mask; +static inline bool btree_id_is_extents(enum btree_id btree) +{ + return BIT_ULL(btree) & btree_is_extents_mask; } static inline bool btree_node_type_is_extents(enum btree_node_type type) @@ -866,6 +867,11 @@ static inline bool btree_type_has_snapshots(enum btree_id btree) return BIT_ULL(btree) & btree_has_snapshots_mask; } +static inline bool btree_id_is_extents_snapshots(enum btree_id btree) +{ + return BIT_ULL(btree) & btree_has_snapshots_mask & btree_is_extents_mask; +} + static inline bool btree_type_has_snapshot_field(enum btree_id btree) { const u64 mask = 0 diff --git a/fs/bcachefs/btree_update.c b/fs/bcachefs/btree_update.c index 566478728aa2..6f3b57573cba 100644 --- a/fs/bcachefs/btree_update.c +++ b/fs/bcachefs/btree_update.c @@ -215,7 +215,7 @@ int bch2_trans_update_extent_overwrite(struct btree_trans *trans, return ret; } - if (bkey_le(old.k->p, new.k->p)) { + if (!back_split) { update = bch2_trans_kmalloc(trans, sizeof(*update)); if ((ret = PTR_ERR_OR_ZERO(update))) return ret; @@ -238,9 +238,7 @@ int bch2_trans_update_extent_overwrite(struct btree_trans *trans, BTREE_UPDATE_internal_snapshot_node|flags); if (ret) return ret; - } - - if (back_split) { + } else { update = bch2_bkey_make_mut_noupdate(trans, old); if ((ret = PTR_ERR_OR_ZERO(update))) return ret; diff --git a/fs/bcachefs/btree_update.h b/fs/bcachefs/btree_update.h index 6790e0254a63..663739db82b1 100644 --- a/fs/bcachefs/btree_update.h +++ b/fs/bcachefs/btree_update.h @@ -370,72 +370,52 @@ static inline struct bkey_i *bch2_bkey_make_mut(struct btree_trans *trans, bkey_i_to_##_type(__bch2_bkey_make_mut(_trans, _iter, _k, _flags,\ KEY_TYPE_##_type, sizeof(struct bkey_i_##_type))) -static inline struct bkey_i *__bch2_bkey_get_mut_noupdate(struct btree_trans *trans, - struct btree_iter *iter, - unsigned btree_id, struct bpos pos, - enum btree_iter_update_trigger_flags flags, +static inline struct bkey_i *__bch2_bkey_get_mut_noupdate(struct btree_iter *iter, unsigned type, unsigned min_bytes) { - struct bkey_s_c k = __bch2_bkey_get_iter(trans, iter, - btree_id, pos, flags|BTREE_ITER_intent, type); - struct bkey_i *ret = IS_ERR(k.k) + struct bkey_s_c k = __bch2_bkey_get_typed(iter, type); + return IS_ERR(k.k) ? ERR_CAST(k.k) - : __bch2_bkey_make_mut_noupdate(trans, k, 0, min_bytes); - if (IS_ERR(ret)) - bch2_trans_iter_exit(iter); - return ret; + : __bch2_bkey_make_mut_noupdate(iter->trans, k, 0, min_bytes); } -static inline struct bkey_i *bch2_bkey_get_mut_noupdate(struct btree_trans *trans, - struct btree_iter *iter, - unsigned btree_id, struct bpos pos, - enum btree_iter_update_trigger_flags flags) +static inline struct bkey_i *bch2_bkey_get_mut_noupdate(struct btree_iter *iter) { - return __bch2_bkey_get_mut_noupdate(trans, iter, btree_id, pos, flags, 0, 0); + return __bch2_bkey_get_mut_noupdate(iter, 0, 0); } static inline struct bkey_i *__bch2_bkey_get_mut(struct btree_trans *trans, - struct btree_iter *iter, - unsigned btree_id, struct bpos pos, + enum btree_id btree, struct bpos pos, enum btree_iter_update_trigger_flags flags, unsigned type, unsigned min_bytes) { - struct bkey_i *mut = __bch2_bkey_get_mut_noupdate(trans, iter, - btree_id, pos, flags|BTREE_ITER_intent, type, min_bytes); - int ret; - + CLASS(btree_iter, iter)(trans, btree, pos, flags|BTREE_ITER_intent); + struct bkey_i *mut = __bch2_bkey_get_mut_noupdate(&iter, type, min_bytes); if (IS_ERR(mut)) return mut; - - ret = bch2_trans_update(trans, iter, mut, flags); - if (ret) { - bch2_trans_iter_exit(iter); + int ret = bch2_trans_update(trans, &iter, mut, flags); + if (ret) return ERR_PTR(ret); - } - return mut; } static inline struct bkey_i *bch2_bkey_get_mut_minsize(struct btree_trans *trans, - struct btree_iter *iter, unsigned btree_id, struct bpos pos, enum btree_iter_update_trigger_flags flags, unsigned min_bytes) { - return __bch2_bkey_get_mut(trans, iter, btree_id, pos, flags, 0, min_bytes); + return __bch2_bkey_get_mut(trans, btree_id, pos, flags, 0, min_bytes); } static inline struct bkey_i *bch2_bkey_get_mut(struct btree_trans *trans, - struct btree_iter *iter, unsigned btree_id, struct bpos pos, enum btree_iter_update_trigger_flags flags) { - return __bch2_bkey_get_mut(trans, iter, btree_id, pos, flags, 0, 0); + return __bch2_bkey_get_mut(trans, btree_id, pos, flags, 0, 0); } -#define bch2_bkey_get_mut_typed(_trans, _iter, _btree_id, _pos, _flags, _type)\ - bkey_i_to_##_type(__bch2_bkey_get_mut(_trans, _iter, \ - _btree_id, _pos, _flags, \ +#define bch2_bkey_get_mut_typed(_trans, _btree_id, _pos, _flags, _type) \ + bkey_i_to_##_type(__bch2_bkey_get_mut(_trans, _btree_id, _pos, _flags, \ KEY_TYPE_##_type, sizeof(struct bkey_i_##_type))) static inline struct bkey_i *__bch2_bkey_alloc(struct btree_trans *trans, struct btree_iter *iter, diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 5f4f82967105..76897cf15946 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -66,6 +66,10 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b) bkey_init(&prev.k->k); bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b); + /* + * Don't use btree_node_is_root(): we're called by btree split, after + * creating a new root but before setting it + */ if (b == btree_node_root(c, b)) { if (!bpos_eq(b->data->min_key, POS_MIN)) { bch2_log_msg_start(c, &buf); @@ -1655,7 +1659,7 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans, int ret = 0; bch2_verify_btree_nr_keys(b); - BUG_ON(!parent && (b != btree_node_root(c, b))); + BUG_ON(!parent && !btree_node_is_root(c, b)); BUG_ON(parent && !btree_node_intent_locked(trans->paths + path, b->c.level + 1)); ret = bch2_btree_node_check_topology(trans, b); @@ -2527,7 +2531,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans, if (ret) goto err; } else { - BUG_ON(btree_node_root(c, b) != b); + BUG_ON(!btree_node_is_root(c, b)); struct jset_entry *e = bch2_trans_jset_entry_alloc(trans, jset_u64s(new_key->k.u64s)); diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 0a357005e9e8..87a6f4dce296 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -663,24 +663,23 @@ static int bch2_trigger_stripe_ptr(struct btree_trans *trans, struct bch_fs *c = trans->c; if (flags & BTREE_TRIGGER_transactional) { - struct btree_iter iter; - struct bkey_i_stripe *s = bch2_bkey_get_mut_typed(trans, &iter, - BTREE_ID_stripes, POS(0, p.ec.idx), - BTREE_ITER_with_updates, stripe); + struct bkey_i_stripe *s = bch2_bkey_get_mut_typed(trans, + BTREE_ID_stripes, POS(0, p.ec.idx), + BTREE_ITER_with_updates, + stripe); int ret = PTR_ERR_OR_ZERO(s); if (unlikely(ret)) { bch2_trans_inconsistent_on(bch2_err_matches(ret, ENOENT), trans, "pointer to nonexistent stripe %llu", (u64) p.ec.idx); - goto err; + return ret; } if (!bch2_ptr_matches_stripe(&s->v, p)) { bch2_trans_inconsistent(trans, "stripe pointer doesn't match stripe %llu", (u64) p.ec.idx); - ret = bch_err_throw(c, trigger_stripe_pointer); - goto err; + return bch_err_throw(c, trigger_stripe_pointer); } stripe_blockcount_set(&s->v, p.ec.block, @@ -692,10 +691,7 @@ static int bch2_trigger_stripe_ptr(struct btree_trans *trans, acc.type = BCH_DISK_ACCOUNTING_replicas; bch2_bkey_to_replicas(&acc.replicas, bkey_i_to_s_c(&s->k_i)); acc.replicas.data_type = data_type; - ret = bch2_disk_accounting_mod(trans, &acc, §ors, 1, false); -err: - bch2_trans_iter_exit(&iter); - return ret; + return bch2_disk_accounting_mod(trans, &acc, §ors, 1, false); } if (flags & BTREE_TRIGGER_gc) { diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c index 982d8ec17803..cb44b35e0f1d 100644 --- a/fs/bcachefs/dirent.c +++ b/fs/bcachefs/dirent.c @@ -740,21 +740,22 @@ found: int bch2_fsck_remove_dirent(struct btree_trans *trans, struct bpos pos) { struct bch_fs *c = trans->c; - struct bch_inode_unpacked dir_inode; - struct bch_hash_info dir_hash_info; + struct bch_inode_unpacked dir_inode; int ret = lookup_first_inode(trans, pos.inode, &dir_inode); if (ret) goto err; - dir_hash_info = bch2_hash_info_init(c, &dir_inode); + { + struct bch_hash_info dir_hash_info = bch2_hash_info_init(c, &dir_inode); - CLASS(btree_iter, iter)(trans, BTREE_ID_dirents, pos, BTREE_ITER_intent); + CLASS(btree_iter, iter)(trans, BTREE_ID_dirents, pos, BTREE_ITER_intent); - ret = bch2_btree_iter_traverse(&iter) ?: - bch2_hash_delete_at(trans, bch2_dirent_hash_desc, - &dir_hash_info, &iter, - BTREE_UPDATE_internal_snapshot_node); + ret = bch2_btree_iter_traverse(&iter) ?: + bch2_hash_delete_at(trans, bch2_dirent_hash_desc, + &dir_hash_info, &iter, + BTREE_UPDATE_internal_snapshot_node); + } err: bch_err_fn(c, ret); return ret; diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index 685acadeeae7..6ccea09243ab 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -190,8 +190,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot, return ret; if (!subvol.inode) { - struct btree_iter iter; - struct bkey_i_subvolume *subvol = bch2_bkey_get_mut_typed(trans, &iter, + struct bkey_i_subvolume *subvol = bch2_bkey_get_mut_typed(trans, BTREE_ID_subvolumes, POS(0, subvolid), 0, subvolume); ret = PTR_ERR_OR_ZERO(subvol); @@ -199,7 +198,6 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot, return ret; subvol->v.inode = cpu_to_le64(reattaching_inum); - bch2_trans_iter_exit(&iter); } subvol_inum root_inum = { @@ -369,9 +367,8 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked * if (inode->bi_subvol) { inode->bi_parent_subvol = BCACHEFS_ROOT_SUBVOL; - struct btree_iter subvol_iter; struct bkey_i_subvolume *subvol = - bch2_bkey_get_mut_typed(trans, &subvol_iter, + bch2_bkey_get_mut_typed(trans, BTREE_ID_subvolumes, POS(0, inode->bi_subvol), 0, subvolume); ret = PTR_ERR_OR_ZERO(subvol); @@ -379,7 +376,6 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked * return ret; subvol->v.fs_path_parent = BCACHEFS_ROOT_SUBVOL; - bch2_trans_iter_exit(&subvol_iter); u64 root_inum; ret = subvol_lookup(trans, inode->bi_parent_subvol, @@ -602,8 +598,7 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub if (ret) return ret; - struct btree_iter iter; - struct bkey_i_snapshot *s = bch2_bkey_get_mut_typed(trans, &iter, + struct bkey_i_snapshot *s = bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshots, POS(0, snapshotid), 0, snapshot); ret = PTR_ERR_OR_ZERO(s); @@ -615,9 +610,8 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub s->v.subvol = cpu_to_le32(subvolid); SET_BCH_SNAPSHOT_SUBVOL(&s->v, true); - bch2_trans_iter_exit(&iter); - struct bkey_i_snapshot_tree *st = bch2_bkey_get_mut_typed(trans, &iter, + struct bkey_i_snapshot_tree *st = bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshot_trees, POS(0, snapshot_tree), 0, snapshot_tree); ret = PTR_ERR_OR_ZERO(st); @@ -627,8 +621,6 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub if (!st->v.master_subvol) st->v.master_subvol = cpu_to_le32(subvolid); - - bch2_trans_iter_exit(&iter); return 0; } @@ -931,9 +923,10 @@ lookup_inode_for_snapshot(struct btree_trans *trans, struct inode_walker *w, str bkey_init(&whiteout.k); whiteout.k.type = KEY_TYPE_whiteout; whiteout.k.p = SPOS(0, i->inode.bi_inum, k.k->p.snapshot); - ret = bch2_btree_insert_nonextent(trans, BTREE_ID_inodes, - &whiteout, - BTREE_UPDATE_internal_snapshot_node); + ret = bch2_btree_insert_trans(trans, BTREE_ID_inodes, + &whiteout, + BTREE_ITER_cached| + BTREE_UPDATE_internal_snapshot_node); } if (ret) @@ -2129,6 +2122,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter * struct bkey_s_c_dirent d) { struct bch_fs *c = trans->c; + struct btree_iter subvol_iter = {}; struct bch_inode_unpacked subvol_root; u32 parent_subvol = le32_to_cpu(d.v->d_parent_subvol); u32 target_subvol = le32_to_cpu(d.v->d_child_subvol); @@ -2185,18 +2179,19 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter * new_dirent->v.d_parent_subvol = cpu_to_le32(new_parent_subvol); } - CLASS(btree_iter, subvol_iter)(trans, BTREE_ID_subvolumes, POS(0, target_subvol), 0); + bch2_trans_iter_init(trans, &subvol_iter, BTREE_ID_subvolumes, POS(0, target_subvol), 0); struct bkey_s_c_subvolume s = bch2_bkey_get_typed(&subvol_iter, subvolume); ret = bkey_err(s.s_c); if (ret && !bch2_err_matches(ret, ENOENT)) - return ret; + goto err; if (ret) { if (fsck_err(trans, dirent_to_missing_subvol, "dirent points to missing subvolume\n%s", (bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf))) return bch2_fsck_remove_dirent(trans, d.k->p); - return 0; + ret = 0; + goto out; } if (le32_to_cpu(s.v->fs_path_parent) != parent_subvol) { @@ -2208,7 +2203,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter * ret = bch2_inum_to_path(trans, (subvol_inum) { s.k->p.offset, le64_to_cpu(s.v->inode) }, &buf); if (ret) - return ret; + goto err; prt_newline(&buf); bch2_bkey_val_to_text(&buf, c, s.s_c); @@ -2217,7 +2212,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter * bch2_bkey_make_mut_typed(trans, &subvol_iter, &s.s_c, 0, subvolume); ret = PTR_ERR_OR_ZERO(n); if (ret) - return ret; + goto err; n->v.fs_path_parent = cpu_to_le32(parent_subvol); } @@ -2229,11 +2224,12 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter * ret = bch2_inode_find_by_inum_snapshot(trans, target_inum, target_snapshot, &subvol_root, 0); if (ret && !bch2_err_matches(ret, ENOENT)) - return ret; + goto err; if (ret) { bch_err(c, "subvol %u points to missing inode root %llu", target_subvol, target_inum); - return bch_err_throw(c, fsck_repair_unimplemented); + ret = bch_err_throw(c, fsck_repair_unimplemented); + goto err; } if (fsck_err_on(!ret && parent_subvol != subvol_root.bi_parent_subvol, @@ -2245,13 +2241,16 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter * subvol_root.bi_snapshot = le32_to_cpu(s.v->snapshot); ret = __bch2_fsck_write_inode(trans, &subvol_root); if (ret) - return ret; + goto err; } ret = bch2_check_dirent_target(trans, iter, d, &subvol_root, true); if (ret) - return ret; + goto err; +out: +err: fsck_err: + bch2_trans_iter_exit(&subvol_iter); return ret; } diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index 85013e8d6166..d5e5190f0663 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -463,9 +463,10 @@ int __bch2_fsck_write_inode(struct btree_trans *trans, struct bch_inode_unpacked bch2_inode_pack(inode_p, inode); inode_p->inode.k.p.snapshot = inode->bi_snapshot; - return bch2_btree_insert_nonextent(trans, BTREE_ID_inodes, - &inode_p->inode.k_i, - BTREE_UPDATE_internal_snapshot_node); + return bch2_btree_insert_trans(trans, BTREE_ID_inodes, + &inode_p->inode.k_i, + BTREE_ITER_cached| + BTREE_UPDATE_internal_snapshot_node); } int bch2_fsck_write_inode(struct btree_trans *trans, struct bch_inode_unpacked *inode) diff --git a/fs/bcachefs/io_misc.c b/fs/bcachefs/io_misc.c index 3f9defd144a4..fa0b06e17d17 100644 --- a/fs/bcachefs/io_misc.c +++ b/fs/bcachefs/io_misc.c @@ -274,13 +274,15 @@ static int __bch2_resume_logged_op_truncate(struct btree_trans *trans, if (ret) goto err; - CLASS(btree_iter, fpunch_iter)(trans, BTREE_ID_extents, - POS(inum.inum, round_up(new_i_size, block_bytes(c)) >> 9), - BTREE_ITER_intent); - ret = bch2_fpunch_at(trans, &fpunch_iter, inum, U64_MAX, i_sectors_delta); + { + CLASS(btree_iter, fpunch_iter)(trans, BTREE_ID_extents, + POS(inum.inum, round_up(new_i_size, block_bytes(c)) >> 9), + BTREE_ITER_intent); + ret = bch2_fpunch_at(trans, &fpunch_iter, inum, U64_MAX, i_sectors_delta); - if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) - ret = 0; + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) + ret = 0; + } err: if (warn_errors) bch_err_fn(c, ret); diff --git a/fs/bcachefs/logged_ops.h b/fs/bcachefs/logged_ops.h index 30ae9ef737dd..6dea6e2ac7a8 100644 --- a/fs/bcachefs/logged_ops.h +++ b/fs/bcachefs/logged_ops.h @@ -10,7 +10,7 @@ static inline int bch2_logged_op_update(struct btree_trans *trans, struct bkey_i *op) { - return bch2_btree_insert_nonextent(trans, BTREE_ID_logged_ops, op, 0); + return bch2_btree_insert_trans(trans, BTREE_ID_logged_ops, op, BTREE_ITER_cached); } int bch2_resume_logged_ops(struct bch_fs *); diff --git a/fs/bcachefs/namei.c b/fs/bcachefs/namei.c index 5cb12db311e3..d1019052f182 100644 --- a/fs/bcachefs/namei.c +++ b/fs/bcachefs/namei.c @@ -383,9 +383,8 @@ bool bch2_reinherit_attrs(struct bch_inode_unpacked *dst_u, static int subvol_update_parent(struct btree_trans *trans, u32 subvol, u32 new_parent) { - struct btree_iter iter; struct bkey_i_subvolume *s = - bch2_bkey_get_mut_typed(trans, &iter, + bch2_bkey_get_mut_typed(trans, BTREE_ID_subvolumes, POS(0, subvol), BTREE_ITER_cached, subvolume); int ret = PTR_ERR_OR_ZERO(s); @@ -393,7 +392,6 @@ static int subvol_update_parent(struct btree_trans *trans, u32 subvol, u32 new_p return ret; s->v.fs_path_parent = cpu_to_le32(new_parent); - bch2_trans_iter_exit(&iter); return 0; } @@ -745,6 +743,7 @@ static int bch2_check_dirent_inode_dirent(struct btree_trans *trans, { struct bch_fs *c = trans->c; CLASS(printbuf, buf)(); + struct btree_iter bp_iter = {}; int ret = 0; if (inode_points_to_dirent(target, d)) @@ -775,8 +774,8 @@ static int bch2_check_dirent_inode_dirent(struct btree_trans *trans, return __bch2_fsck_write_inode(trans, target); } - CLASS(btree_iter, bp_iter)(trans, BTREE_ID_dirents, - SPOS(target->bi_dir, target->bi_dir_offset, target->bi_snapshot), 0); + bch2_trans_iter_init(trans, &bp_iter, BTREE_ID_dirents, + SPOS(target->bi_dir, target->bi_dir_offset, target->bi_snapshot), 0); struct bkey_s_c_dirent bp_dirent = bch2_bkey_get_typed(&bp_iter, dirent); ret = bkey_err(bp_dirent); if (ret && !bch2_err_matches(ret, ENOENT)) @@ -826,6 +825,8 @@ static int bch2_check_dirent_inode_dirent(struct btree_trans *trans, S_ISDIR(target->bi_mode) ? "directory" : "subvolume", target->bi_inum, target->bi_snapshot, buf.buf); } + + goto out; } else { /* * hardlinked file with nlink 0: @@ -839,11 +840,15 @@ static int bch2_check_dirent_inode_dirent(struct btree_trans *trans, target->bi_nlink++; target->bi_flags &= ~BCH_INODE_unlinked; ret = __bch2_fsck_write_inode(trans, target); + if (ret) + goto err; } } } +out: err: fsck_err: + bch2_trans_iter_exit(&bp_iter); bch_err_fn(c, ret); return ret; } diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h index dd4ee46606d7..5317b1bfe2e5 100644 --- a/fs/bcachefs/sb-errors_format.h +++ b/fs/bcachefs/sb-errors_format.h @@ -76,6 +76,8 @@ enum bch_fsck_flags { x(btree_node_read_error, 62, FSCK_AUTOFIX) \ x(btree_node_topology_bad_min_key, 63, FSCK_AUTOFIX) \ x(btree_node_topology_bad_max_key, 64, FSCK_AUTOFIX) \ + x(btree_node_topology_bad_root_min_key, 323, FSCK_AUTOFIX) \ + x(btree_node_topology_bad_root_max_key, 324, FSCK_AUTOFIX) \ x(btree_node_topology_overwritten_by_prev_node, 65, FSCK_AUTOFIX) \ x(btree_node_topology_overwritten_by_next_node, 66, FSCK_AUTOFIX) \ x(btree_node_topology_interior_node_empty, 67, FSCK_AUTOFIX) \ @@ -334,7 +336,7 @@ enum bch_fsck_flags { x(dirent_stray_data_after_cf_name, 305, 0) \ x(rebalance_work_incorrectly_set, 309, FSCK_AUTOFIX) \ x(rebalance_work_incorrectly_unset, 310, FSCK_AUTOFIX) \ - x(MAX, 323, 0) + x(MAX, 325, 0) enum bch_sb_error_id { #define x(t, n, ...) BCH_FSCK_ERR_##t = n, diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index 56de79998712..5a1f81749661 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c @@ -452,17 +452,14 @@ static int bch2_snapshot_tree_master_subvol(struct btree_trans *trans, *subvol_id = bch2_snapshot_oldest_subvol(c, snapshot_root, NULL); - struct btree_iter iter; struct bkey_i_subvolume *u = - bch2_bkey_get_mut_typed(trans, &iter, - BTREE_ID_subvolumes, POS(0, *subvol_id), + bch2_bkey_get_mut_typed(trans, BTREE_ID_subvolumes, POS(0, *subvol_id), 0, subvolume); ret = PTR_ERR_OR_ZERO(u); if (ret) return ret; SET_BCH_SUBVOLUME_SNAP(&u->v, false); - bch2_trans_iter_exit(&iter); return 0; } @@ -1087,28 +1084,21 @@ int __bch2_get_snapshot_overwrites(struct btree_trans *trans, */ int bch2_snapshot_node_set_deleted(struct btree_trans *trans, u32 id) { - struct btree_iter iter; struct bkey_i_snapshot *s = - bch2_bkey_get_mut_typed(trans, &iter, - BTREE_ID_snapshots, POS(0, id), - 0, snapshot); + bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshots, POS(0, id), 0, snapshot); int ret = PTR_ERR_OR_ZERO(s); - if (unlikely(ret)) { - bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), - trans->c, "missing snapshot %u", id); + bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c, "missing snapshot %u", id); + if (unlikely(ret)) return ret; - } /* already deleted? */ if (BCH_SNAPSHOT_WILL_DELETE(&s->v)) - goto err; + return 0; SET_BCH_SNAPSHOT_WILL_DELETE(&s->v, true); SET_BCH_SNAPSHOT_SUBVOL(&s->v, false); s->v.subvol = 0; -err: - bch2_trans_iter_exit(&iter); - return ret; + return 0; } static inline void normalize_snapshot_child_pointers(struct bch_snapshot *s) @@ -1120,22 +1110,17 @@ static inline void normalize_snapshot_child_pointers(struct bch_snapshot *s) static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) { struct bch_fs *c = trans->c; - struct btree_iter iter, p_iter = {}; - struct btree_iter c_iter = {}; - struct btree_iter tree_iter = {}; u32 parent_id, child_id; unsigned i; - int ret = 0; struct bkey_i_snapshot *s = - bch2_bkey_get_mut_typed(trans, &iter, BTREE_ID_snapshots, POS(0, id), - BTREE_ITER_intent, snapshot); - ret = PTR_ERR_OR_ZERO(s); + bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshots, POS(0, id), 0, snapshot); + int ret = PTR_ERR_OR_ZERO(s); bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c, "missing snapshot %u", id); if (ret) - goto err; + return ret; BUG_ON(BCH_SNAPSHOT_DELETED(&s->v)); BUG_ON(s->v.children[1]); @@ -1144,16 +1129,14 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) child_id = le32_to_cpu(s->v.children[0]); if (parent_id) { - struct bkey_i_snapshot *parent; - - parent = bch2_bkey_get_mut_typed(trans, &p_iter, - BTREE_ID_snapshots, POS(0, parent_id), - 0, snapshot); + struct bkey_i_snapshot *parent = + bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshots, POS(0, parent_id), + 0, snapshot); ret = PTR_ERR_OR_ZERO(parent); bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c, "missing snapshot %u", parent_id); if (unlikely(ret)) - goto err; + return ret; /* find entry in parent->children for node being deleted */ for (i = 0; i < 2; i++) @@ -1163,7 +1146,7 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) if (bch2_fs_inconsistent_on(i == 2, c, "snapshot %u missing child pointer to %u", parent_id, id)) - goto err; + return ret; parent->v.children[i] = cpu_to_le32(child_id); @@ -1171,16 +1154,14 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) } if (child_id) { - struct bkey_i_snapshot *child; - - child = bch2_bkey_get_mut_typed(trans, &c_iter, - BTREE_ID_snapshots, POS(0, child_id), - 0, snapshot); + struct bkey_i_snapshot *child = + bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshots, POS(0, child_id), + 0, snapshot); ret = PTR_ERR_OR_ZERO(child); bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c, "missing snapshot %u", child_id); if (unlikely(ret)) - goto err; + return ret; child->v.parent = cpu_to_le32(parent_id); @@ -1197,16 +1178,15 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) * snapshot_tree entry to point to the new root, or delete it if * this is the last snapshot ID in this tree: */ - struct bkey_i_snapshot_tree *s_t; BUG_ON(s->v.children[1]); - s_t = bch2_bkey_get_mut_typed(trans, &tree_iter, + struct bkey_i_snapshot_tree *s_t = bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshot_trees, POS(0, le32_to_cpu(s->v.tree)), 0, snapshot_tree); ret = PTR_ERR_OR_ZERO(s_t); if (ret) - goto err; + return ret; if (s->v.children[0]) { s_t->v.root_snapshot = s->v.children[0]; @@ -1231,12 +1211,8 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) s->k.type = KEY_TYPE_deleted; set_bkey_val_u64s(&s->k, 0); } -err: - bch2_trans_iter_exit(&tree_iter); - bch2_trans_iter_exit(&p_iter); - bch2_trans_iter_exit(&c_iter); - bch2_trans_iter_exit(&iter); - return ret; + + return 0; } static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree, @@ -1248,8 +1224,7 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree, struct bkey_i_snapshot *n; u32 depth = bch2_snapshot_depth(c, parent); - CLASS(btree_iter, iter)(trans, BTREE_ID_snapshots, - POS_MIN, BTREE_ITER_intent); + CLASS(btree_iter, iter)(trans, BTREE_ID_snapshots, POS_MIN, BTREE_ITER_intent); struct bkey_s_c k = bch2_btree_iter_peek(&iter); int ret = bkey_err(k); if (ret) @@ -1303,14 +1278,9 @@ static int bch2_snapshot_node_create_children(struct btree_trans *trans, u32 par u32 *snapshot_subvols, unsigned nr_snapids) { - struct btree_iter iter; - struct bkey_i_snapshot *n_parent; - int ret = 0; - - n_parent = bch2_bkey_get_mut_typed(trans, &iter, - BTREE_ID_snapshots, POS(0, parent), - 0, snapshot); - ret = PTR_ERR_OR_ZERO(n_parent); + struct bkey_i_snapshot *n_parent = + bch2_bkey_get_mut_typed(trans, BTREE_ID_snapshots, POS(0, parent), 0, snapshot); + int ret = PTR_ERR_OR_ZERO(n_parent); if (unlikely(ret)) { if (bch2_err_matches(ret, ENOENT)) bch_err(trans->c, "snapshot %u not found", parent); @@ -1319,22 +1289,19 @@ static int bch2_snapshot_node_create_children(struct btree_trans *trans, u32 par if (n_parent->v.children[0] || n_parent->v.children[1]) { bch_err(trans->c, "Trying to add child snapshot nodes to parent that already has children"); - ret = -EINVAL; - goto err; + return -EINVAL; } ret = create_snapids(trans, parent, le32_to_cpu(n_parent->v.tree), new_snapids, snapshot_subvols, nr_snapids); if (ret) - goto err; + return ret; n_parent->v.children[0] = cpu_to_le32(new_snapids[0]); n_parent->v.children[1] = cpu_to_le32(new_snapids[1]); n_parent->v.subvol = 0; SET_BCH_SNAPSHOT_SUBVOL(&n_parent->v, false); -err: - bch2_trans_iter_exit(&iter); - return ret; + return 0; } /* diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c index 9145b7e73481..6023ae46ca72 100644 --- a/fs/bcachefs/subvolume.c +++ b/fs/bcachefs/subvolume.c @@ -539,13 +539,8 @@ static int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans int bch2_subvolume_unlink(struct btree_trans *trans, u32 subvolid) { - struct btree_iter iter; - struct bkey_i_subvolume *n; - struct subvolume_unlink_hook *h; - int ret = 0; - - h = bch2_trans_kmalloc(trans, sizeof(*h)); - ret = PTR_ERR_OR_ZERO(h); + struct subvolume_unlink_hook *h = bch2_trans_kmalloc(trans, sizeof(*h)); + int ret = PTR_ERR_OR_ZERO(h); if (ret) return ret; @@ -553,9 +548,9 @@ int bch2_subvolume_unlink(struct btree_trans *trans, u32 subvolid) h->subvol = subvolid; bch2_trans_commit_hook(trans, &h->h); - n = bch2_bkey_get_mut_typed(trans, &iter, - BTREE_ID_subvolumes, POS(0, subvolid), - BTREE_ITER_cached, subvolume); + struct bkey_i_subvolume *n = + bch2_bkey_get_mut_typed(trans, BTREE_ID_subvolumes, POS(0, subvolid), + BTREE_ITER_cached, subvolume); ret = PTR_ERR_OR_ZERO(n); if (bch2_err_matches(ret, ENOENT)) ret = bch2_subvolume_missing(trans->c, subvolid) ?: ret; @@ -564,7 +559,6 @@ int bch2_subvolume_unlink(struct btree_trans *trans, u32 subvolid) SET_BCH_SUBVOLUME_UNLINKED(&n->v, true); n->v.fs_path_parent = 0; - bch2_trans_iter_exit(&iter); return ret; } @@ -576,7 +570,7 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode, bool ro) { struct bch_fs *c = trans->c; - struct btree_iter dst_iter, src_iter = (struct btree_iter) { NULL }; + struct btree_iter dst_iter; struct bkey_i_subvolume *new_subvol = NULL; struct bkey_i_subvolume *src_subvol = NULL; u32 parent = 0, new_nodes[2], snapshot_subvols[2]; @@ -595,9 +589,8 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode, if (src_subvolid) { /* Creating a snapshot: */ - src_subvol = bch2_bkey_get_mut_typed(trans, &src_iter, - BTREE_ID_subvolumes, POS(0, src_subvolid), - BTREE_ITER_cached, subvolume); + src_subvol = bch2_bkey_get_mut_typed(trans, BTREE_ID_subvolumes, POS(0, src_subvolid), + BTREE_ITER_cached, subvolume); ret = PTR_ERR_OR_ZERO(src_subvol); if (bch2_err_matches(ret, ENOENT)) ret = bch2_subvolume_missing(trans->c, src_subvolid) ?: ret; @@ -613,12 +606,8 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode, if (ret) goto err; - if (src_subvolid) { + if (src_subvolid) src_subvol->v.snapshot = cpu_to_le32(new_nodes[1]); - ret = bch2_trans_update(trans, &src_iter, &src_subvol->k_i, 0); - if (ret) - goto err; - } new_subvol = bch2_bkey_alloc(trans, &dst_iter, 0, subvolume); ret = PTR_ERR_OR_ZERO(new_subvol); @@ -639,7 +628,6 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode, *new_subvolid = new_subvol->k.p.offset; *new_snapshotid = new_nodes[0]; err: - bch2_trans_iter_exit(&src_iter); bch2_trans_iter_exit(&dst_iter); return ret; } diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index c88759964575..be7ed612d28f 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -68,28 +68,33 @@ enum bcachefs_metadata_version bch2_latest_compatible_version(enum bcachefs_meta int bch2_set_version_incompat(struct bch_fs *c, enum bcachefs_metadata_version version) { - guard(mutex)(&c->sb_lock); - if (((c->sb.features & BIT_ULL(BCH_FEATURE_incompat_version_field)) && version <= c->sb.version_incompat_allowed)) { - SET_BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb, - max(BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb), version)); - bch2_write_super(c); + guard(mutex)(&c->sb_lock); + + if (version > c->sb.version_incompat) { + SET_BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb, + max(BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb), version)); + bch2_write_super(c); + } return 0; } else { - darray_for_each(c->incompat_versions_requested, i) - if (version == *i) - return bch_err_throw(c, may_not_use_incompat_feature); + BUILD_BUG_ON(BCH_VERSION_MAJOR(bcachefs_metadata_version_current) != 1); - darray_push(&c->incompat_versions_requested, version); - CLASS(printbuf, buf)(); - prt_str(&buf, "requested incompat feature "); - bch2_version_to_text(&buf, version); - prt_str(&buf, " currently not enabled, allowed up to "); - bch2_version_to_text(&buf, version); - prt_printf(&buf, "\n set version_upgrade=incompat to enable"); + unsigned minor = BCH_VERSION_MINOR(version); + + if (!test_bit(minor, c->incompat_versions_requested) && + !test_and_set_bit(minor, c->incompat_versions_requested)) { + CLASS(printbuf, buf)(); + prt_str(&buf, "requested incompat feature "); + bch2_version_to_text(&buf, version); + prt_str(&buf, " currently not enabled, allowed up to "); + bch2_version_to_text(&buf, version); + prt_printf(&buf, "\n set version_upgrade=incompat to enable"); + + bch_notice(c, "%s", buf.buf); + } - bch_notice(c, "%s", buf.buf); return bch_err_throw(c, may_not_use_incompat_feature); } } diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index b3b2d8353a36..b0019488f586 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -653,7 +653,6 @@ static void __bch2_fs_free(struct bch_fs *c) free_percpu(c->online_reserved); } - darray_exit(&c->incompat_versions_requested); darray_exit(&c->btree_roots_extra); free_percpu(c->pcpu); free_percpu(c->usage); |