summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/alloc_background.c64
-rw-r--r--fs/bcachefs/backpointers.c28
-rw-r--r--fs/bcachefs/bcachefs.h4
-rw-r--r--fs/bcachefs/btree_cache.c2
-rw-r--r--fs/bcachefs/btree_cache.h8
-rw-r--r--fs/bcachefs/btree_gc.c35
-rw-r--r--fs/bcachefs/btree_iter.c4
-rw-r--r--fs/bcachefs/btree_iter.h2
-rw-r--r--fs/bcachefs/btree_key_cache.c1
-rw-r--r--fs/bcachefs/btree_types.h18
-rw-r--r--fs/bcachefs/btree_update.c6
-rw-r--r--fs/bcachefs/btree_update.h50
-rw-r--r--fs/bcachefs/btree_update_interior.c8
-rw-r--r--fs/bcachefs/buckets.c18
-rw-r--r--fs/bcachefs/dirent.c17
-rw-r--r--fs/bcachefs/fsck.c47
-rw-r--r--fs/bcachefs/inode.c7
-rw-r--r--fs/bcachefs/io_misc.c14
-rw-r--r--fs/bcachefs/logged_ops.h2
-rw-r--r--fs/bcachefs/namei.c15
-rw-r--r--fs/bcachefs/sb-errors_format.h4
-rw-r--r--fs/bcachefs/snapshot.c91
-rw-r--r--fs/bcachefs/subvolume.c30
-rw-r--r--fs/bcachefs/super-io.c37
-rw-r--r--fs/bcachefs/super.c1
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, &sectors, 1, false);
-err:
- bch2_trans_iter_exit(&iter);
- return ret;
+ return bch2_disk_accounting_mod(trans, &acc, &sectors, 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);