summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/bcachefs_format.h11
-rw-r--r--fs/bcachefs/bkey_methods.c6
-rw-r--r--fs/bcachefs/bkey_types.h5
-rw-r--r--fs/bcachefs/btree_gc.c38
-rw-r--r--fs/bcachefs/btree_iter.c72
-rw-r--r--fs/bcachefs/btree_update.c76
-rw-r--r--fs/bcachefs/btree_update_interior.c8
-rw-r--r--fs/bcachefs/errcode.h1
-rw-r--r--fs/bcachefs/fs.c4
-rw-r--r--fs/bcachefs/fsck.c4
-rw-r--r--fs/bcachefs/move.c8
-rw-r--r--fs/bcachefs/sb-counters_format.h2
-rw-r--r--fs/bcachefs/sb-errors_format.h4
-rw-r--r--fs/bcachefs/sb-members.c116
-rw-r--r--fs/bcachefs/sb-members.h25
-rw-r--r--fs/bcachefs/snapshot.c2
16 files changed, 176 insertions, 206 deletions
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index a8f59522e258..b4a04df5ea95 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -423,8 +423,7 @@ enum bch_bkey_type_flags {
x(logged_op_truncate, 32, BKEY_TYPE_strict_btree_checks) \
x(logged_op_finsert, 33, BKEY_TYPE_strict_btree_checks) \
x(accounting, 34, BKEY_TYPE_strict_btree_checks) \
- x(inode_alloc_cursor, 35, BKEY_TYPE_strict_btree_checks) \
- x(extent_whiteout, 36, BKEY_TYPE_strict_btree_checks)
+ x(inode_alloc_cursor, 35, BKEY_TYPE_strict_btree_checks)
enum bch_bkey_type {
#define x(name, nr, ...) KEY_TYPE_##name = nr,
@@ -441,10 +440,6 @@ struct bch_whiteout {
struct bch_val v;
};
-struct bch_extent_whiteout {
- struct bch_val v;
-};
-
struct bch_error {
struct bch_val v;
};
@@ -705,8 +700,7 @@ struct bch_sb_field_ext {
x(extent_flags, BCH_VERSION(1, 25)) \
x(snapshot_deletion_v2, BCH_VERSION(1, 26)) \
x(fast_device_removal, BCH_VERSION(1, 27)) \
- x(inode_has_case_insensitive, BCH_VERSION(1, 28)) \
- x(extent_snapshot_whiteouts, BCH_VERSION(1, 29))
+ x(inode_has_case_insensitive, BCH_VERSION(1, 28))
enum bcachefs_metadata_version {
bcachefs_metadata_version_min = 9,
@@ -1346,7 +1340,6 @@ enum btree_id_flags {
BTREE_IS_snapshots| \
BTREE_IS_data, \
BIT_ULL(KEY_TYPE_whiteout)| \
- BIT_ULL(KEY_TYPE_extent_whiteout)| \
BIT_ULL(KEY_TYPE_error)| \
BIT_ULL(KEY_TYPE_cookie)| \
BIT_ULL(KEY_TYPE_extent)| \
diff --git a/fs/bcachefs/bkey_methods.c b/fs/bcachefs/bkey_methods.c
index 75d73677c4d8..fcd8c82cba4f 100644
--- a/fs/bcachefs/bkey_methods.c
+++ b/fs/bcachefs/bkey_methods.c
@@ -41,10 +41,6 @@ static int deleted_key_validate(struct bch_fs *c, struct bkey_s_c k,
.key_validate = deleted_key_validate, \
})
-#define bch2_bkey_ops_extent_whiteout ((struct bkey_ops) { \
- .key_validate = deleted_key_validate, \
-})
-
static int empty_val_key_validate(struct bch_fs *c, struct bkey_s_c k,
struct bkey_validate_context from)
{
@@ -207,7 +203,7 @@ int __bch2_bkey_validate(struct bch_fs *c, struct bkey_s_c k,
? bch2_bkey_types[k.k->type]
: "(unknown)");
- if (btree_node_type_is_extents(type) && !bkey_extent_whiteout(k.k)) {
+ if (btree_node_type_is_extents(type) && !bkey_whiteout(k.k)) {
bkey_fsck_err_on(k.k->size == 0,
c, bkey_extent_size_zero,
"size == 0");
diff --git a/fs/bcachefs/bkey_types.h b/fs/bcachefs/bkey_types.h
index 88a48ce63656..b4f328f9853c 100644
--- a/fs/bcachefs/bkey_types.h
+++ b/fs/bcachefs/bkey_types.h
@@ -44,11 +44,6 @@ static inline void set_bkey_val_bytes(struct bkey *k, unsigned bytes)
#define bkey_whiteout(_k) \
((_k)->type == KEY_TYPE_deleted || (_k)->type == KEY_TYPE_whiteout)
-#define bkey_extent_whiteout(_k) \
- ((_k)->type == KEY_TYPE_deleted || \
- (_k)->type == KEY_TYPE_whiteout || \
- (_k)->type == KEY_TYPE_extent_whiteout)
-
/* bkey with split value, const */
struct bkey_s_c {
const struct bkey *k;
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index ce3c7750a922..6b91649688da 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -282,6 +282,41 @@ 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));
+
+ prt_str(&buf, " at ");
+ bch2_btree_pos_to_text(&buf, c, b);
+
+ 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 +621,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 8962c481e310..a67babf69d39 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -2450,27 +2450,10 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en
continue;
}
- if (!(iter->flags & BTREE_ITER_nofilter_whiteouts)) {
- /*
- * KEY_TYPE_extent_whiteout indicates that there
- * are no extents that overlap with this
- * whiteout - meaning bkey_start_pos() is
- * monotonically increasing when including
- * KEY_TYPE_extent_whiteout (not
- * KEY_TYPE_whiteout).
- *
- * Without this @end wouldn't be able to
- * terminate searches and we'd have to scan
- * through tons of whiteouts:
- */
- if (k.k->type == KEY_TYPE_extent_whiteout &&
- bkey_ge(k.k->p, end))
- goto end;
-
- if (bkey_extent_whiteout(k.k)) {
- search_key = bkey_successor(iter, k.k->p);
- continue;
- }
+ if (bkey_whiteout(k.k) &&
+ !(iter->flags & BTREE_ITER_nofilter_whiteouts)) {
+ search_key = bkey_successor(iter, k.k->p);
+ continue;
}
}
@@ -2728,7 +2711,7 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp
saved_path = 0;
}
- if (!bkey_extent_whiteout(k.k)) {
+ if (!bkey_whiteout(k.k)) {
saved_path = btree_path_clone(trans, iter->path,
iter->flags & BTREE_ITER_intent,
_THIS_IP_);
@@ -2741,7 +2724,7 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp
continue;
}
- if (bkey_extent_whiteout(k.k)) {
+ if (bkey_whiteout(k.k)) {
search_key = bkey_predecessor(iter, k.k->p);
search_key.snapshot = U32_MAX;
continue;
@@ -2882,7 +2865,7 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
iter->k = *k.k;
}
- if (unlikely(bkey_extent_whiteout(k.k) &&
+ if (unlikely(k.k->type == KEY_TYPE_whiteout &&
(iter->flags & BTREE_ITER_filter_snapshots) &&
!(iter->flags & BTREE_ITER_nofilter_whiteouts)))
iter->k.type = KEY_TYPE_deleted;
@@ -2895,40 +2878,31 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
EBUG_ON(btree_iter_path(trans, iter)->level);
- struct btree_iter iter2;
-
- bch2_trans_copy_iter(&iter2, iter);
- iter2.flags |= BTREE_ITER_nofilter_whiteouts;
+ if (iter->flags & BTREE_ITER_intent) {
+ struct btree_iter iter2;
- while (1) {
+ bch2_trans_copy_iter(&iter2, iter);
k = bch2_btree_iter_peek_max(&iter2, end);
- if ((iter2.flags & BTREE_ITER_is_extents) &&
- k.k &&
- !bkey_err(k) &&
- k.k->type == KEY_TYPE_whiteout) {
- bch2_btree_iter_set_pos(&iter2, k.k->p);
- continue;
- }
- break;
- }
+ if (k.k && !bkey_err(k)) {
+ swap(iter->key_cache_path, iter2.key_cache_path);
+ iter->k = iter2.k;
+ k.k = &iter->k;
+ }
+ bch2_trans_iter_exit(&iter2);
+ } else {
+ struct bpos pos = iter->pos;
- if (k.k && !bkey_err(k)) {
- swap(iter->key_cache_path, iter2.key_cache_path);
- iter->k = iter2.k;
- k.k = &iter->k;
+ k = bch2_btree_iter_peek_max(iter, end);
+ if (unlikely(bkey_err(k)))
+ bch2_btree_iter_set_pos(iter, pos);
+ else
+ iter->pos = pos;
}
- bch2_trans_iter_exit(&iter2);
if (unlikely(bkey_err(k)))
goto out;
- if (unlikely(k.k &&
- bkey_extent_whiteout(k.k) &&
- (iter->flags & BTREE_ITER_filter_snapshots) &&
- !(iter->flags & BTREE_ITER_nofilter_whiteouts)))
- iter->k.type = KEY_TYPE_deleted;
-
next = k.k ? bkey_start_pos(k.k) : POS_MAX;
if (bkey_lt(iter->pos, next)) {
diff --git a/fs/bcachefs/btree_update.c b/fs/bcachefs/btree_update.c
index e0685ae91a70..6f3b57573cba 100644
--- a/fs/bcachefs/btree_update.c
+++ b/fs/bcachefs/btree_update.c
@@ -12,7 +12,6 @@
#include "extents.h"
#include "keylist.h"
#include "snapshot.h"
-#include "super-io.h"
#include "trace.h"
#include <linux/string_helpers.h>
@@ -159,21 +158,6 @@ int __bch2_insert_snapshot_whiteouts(struct btree_trans *trans,
return ret;
}
-static inline enum bch_bkey_type extent_whiteout_type(struct bch_fs *c, enum btree_id btree, const struct bkey *k)
-{
- /*
- * KEY_TYPE_extent_whiteout indicates that there isn't a real extent
- * present at that position: key start positions inclusive of
- * KEY_TYPE_extent_whiteout (but not KEY_TYPE_whiteout) are
- * monotonically increasing
- */
- return btree_id_is_extents_snapshots(btree) &&
- bkey_deleted(k) &&
- !bch2_request_incompat_feature(c, bcachefs_metadata_version_extent_snapshot_whiteouts)
- ? KEY_TYPE_extent_whiteout
- : KEY_TYPE_whiteout;
-}
-
int bch2_trans_update_extent_overwrite(struct btree_trans *trans,
struct btree_iter *iter,
enum btree_iter_update_trigger_flags flags,
@@ -240,19 +224,18 @@ int bch2_trans_update_extent_overwrite(struct btree_trans *trans,
update->k.p = old.k->p;
update->k.p.snapshot = new.k->p.snapshot;
- if (btree_type_has_snapshots(btree_id)) {
- ret = new.k->p.snapshot != old.k->p.snapshot
- ? 1
- : need_whiteout_for_snapshot(trans, btree_id, update->k.p);
+ if (new.k->p.snapshot != old.k->p.snapshot) {
+ update->k.type = KEY_TYPE_whiteout;
+ } else if (btree_type_has_snapshots(btree_id)) {
+ ret = need_whiteout_for_snapshot(trans, btree_id, update->k.p);
if (ret < 0)
return ret;
if (ret)
- update->k.type = extent_whiteout_type(trans->c, iter->btree_id, new.k);
+ update->k.type = KEY_TYPE_whiteout;
}
- ret = bch2_trans_update_by_path(trans, iter->update_path ?: iter->path, update,
- BTREE_UPDATE_internal_snapshot_node|
- flags, _RET_IP_);
+ ret = bch2_btree_insert_nonextent(trans, btree_id, update,
+ BTREE_UPDATE_internal_snapshot_node|flags);
if (ret)
return ret;
} else {
@@ -263,8 +246,8 @@ int bch2_trans_update_extent_overwrite(struct btree_trans *trans,
bch2_cut_front(new.k->p, update);
ret = bch2_trans_update_by_path(trans, iter->path, update,
- BTREE_UPDATE_internal_snapshot_node|
- flags, _RET_IP_);
+ BTREE_UPDATE_internal_snapshot_node|
+ flags, _RET_IP_);
if (ret)
return ret;
}
@@ -282,8 +265,7 @@ static int bch2_trans_update_extent(struct btree_trans *trans,
CLASS(btree_iter, iter)(trans, btree_id, bkey_start_pos(&insert->k),
BTREE_ITER_intent|
BTREE_ITER_with_updates|
- BTREE_ITER_not_extents|
- BTREE_ITER_nofilter_whiteouts);
+ BTREE_ITER_not_extents);
struct bkey_s_c k = bch2_btree_iter_peek_max(&iter, POS(insert->k.p.inode, U64_MAX));
int ret = bkey_err(k);
if (ret)
@@ -301,40 +283,12 @@ static int bch2_trans_update_extent(struct btree_trans *trans,
goto next;
}
- while (true) {
- BUG_ON(bkey_le(k.k->p, bkey_start_pos(&insert->k)));
-
- /*
- * When KEY_TYPE_whiteout is included, bkey_start_pos is not
- * monotonically increasing
- */
- if (k.k->type != KEY_TYPE_whiteout && bkey_le(insert->k.p, bkey_start_pos(k.k)))
- break;
+ while (bkey_gt(insert->k.p, bkey_start_pos(k.k))) {
+ bool done = bkey_lt(insert->k.p, k.k->p);
- bool done = k.k->type != KEY_TYPE_whiteout && bkey_lt(insert->k.p, k.k->p);
-
- if (bkey_extent_whiteout(k.k)) {
- enum bch_bkey_type whiteout_type = extent_whiteout_type(trans->c, btree_id, &insert->k);
-
- if (bkey_le(k.k->p, insert->k.p) &&
- k.k->type != whiteout_type) {
- struct bkey_i *update = bch2_bkey_make_mut_noupdate(trans, k);
- ret = PTR_ERR_OR_ZERO(update);
- if (ret)
- return ret;
-
- update->k.p.snapshot = iter.snapshot;
- update->k.type = whiteout_type;
-
- ret = bch2_trans_update(trans, &iter, update, 0);
- if (ret)
- return ret;
- }
- } else {
- ret = bch2_trans_update_extent_overwrite(trans, &iter, flags, k, bkey_i_to_s_c(insert));
- if (ret)
- return ret;
- }
+ ret = bch2_trans_update_extent_overwrite(trans, &iter, flags, k, bkey_i_to_s_c(insert));
+ if (ret)
+ return ret;
if (done)
goto out;
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index 0952338de28f..76897cf15946 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -66,7 +66,11 @@ 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);
- if (btree_node_is_root(c, 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);
prt_printf(&buf, "btree root with incorrect min_key: ");
@@ -222,7 +226,7 @@ static void __btree_node_free(struct btree_trans *trans, struct btree *b)
BUG_ON(btree_node_write_blocked(b));
BUG_ON(btree_node_dirty(b));
BUG_ON(btree_node_need_write(b));
- BUG_ON(btree_node_is_root(c, b));
+ BUG_ON(b == btree_node_root(c, b));
BUG_ON(b->ob.nr);
BUG_ON(!list_empty(&b->write_blocked));
BUG_ON(b->will_make_reachable);
diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h
index cec8b0f47d3d..adc1f9315eab 100644
--- a/fs/bcachefs/errcode.h
+++ b/fs/bcachefs/errcode.h
@@ -119,6 +119,7 @@
x(ENOENT, ENOENT_not_directory) \
x(ENOENT, ENOENT_directory_dead) \
x(ENOENT, ENOENT_subvolume) \
+ x(ENOENT, ENOENT_snapshot) \
x(ENOENT, ENOENT_snapshot_tree) \
x(ENOENT, ENOENT_dirent_doesnt_match_inode) \
x(ENOENT, ENOENT_dev_not_found) \
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 3b289f696612..b5e3090f1cb8 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -511,8 +511,8 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum)
struct bch_subvolume subvol;
int ret = lockrestart_do(trans,
bch2_subvolume_get(trans, inum.subvol, true, &subvol) ?:
- bch2_inode_find_by_inum_trans(trans, inum, &inode_u)) ?:
- PTR_ERR_OR_ZERO(inode = bch2_inode_hash_init_insert(trans, inum, &inode_u, &subvol));
+ bch2_inode_find_by_inum_trans(trans, inum, &inode_u) ?:
+ PTR_ERR_OR_ZERO(inode = bch2_inode_hash_init_insert(trans, inum, &inode_u, &subvol)));
return ret ? ERR_PTR(ret) : &inode->v;
}
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 01c1c6372229..6ccea09243ab 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -1444,7 +1444,7 @@ static int check_key_has_inode(struct btree_trans *trans,
if (ret)
return ret;
- if (bkey_extent_whiteout(k.k))
+ if (k.k->type == KEY_TYPE_whiteout)
return 0;
bool have_inode = i && !i->whiteout;
@@ -1924,9 +1924,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
&inode->recalculate_sums);
if (ret)
goto err;
- }
- if (!bkey_extent_whiteout(k.k)) {
/*
* Check inodes in reverse order, from oldest snapshots to
* newest, starting from the inode that matches this extent's
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c
index a38996f5366f..30fe269d531d 100644
--- a/fs/bcachefs/move.c
+++ b/fs/bcachefs/move.c
@@ -344,9 +344,13 @@ int bch2_move_extent(struct moving_context *ctxt,
if (!data_opts.rewrite_ptrs &&
!data_opts.extra_replicas &&
!data_opts.scrub) {
- if (data_opts.kill_ptrs)
+ if (data_opts.kill_ptrs) {
+ this_cpu_add(c->counters[BCH_COUNTER_io_move_drop_only], k.k->size);
return bch2_extent_drop_ptrs(trans, iter, k, &io_opts, &data_opts);
- return 0;
+ } else {
+ this_cpu_add(c->counters[BCH_COUNTER_io_move_noop], k.k->size);
+ return 0;
+ }
}
struct moving_io *io = allocate_dropping_locks(trans, ret,
diff --git a/fs/bcachefs/sb-counters_format.h b/fs/bcachefs/sb-counters_format.h
index 2e3a56bfd085..f3ea53a55384 100644
--- a/fs/bcachefs/sb-counters_format.h
+++ b/fs/bcachefs/sb-counters_format.h
@@ -31,6 +31,8 @@ enum counters_flags {
x(io_move_fail, 38, TYPE_COUNTER) \
x(io_move_write_fail, 82, TYPE_COUNTER) \
x(io_move_start_fail, 39, TYPE_COUNTER) \
+ x(io_move_drop_only, 91, TYPE_COUNTER) \
+ x(io_move_noop, 92, TYPE_COUNTER) \
x(io_move_created_rebalance, 83, TYPE_COUNTER) \
x(io_move_evacuate_bucket, 84, TYPE_COUNTER) \
x(bucket_invalidate, 3, TYPE_COUNTER) \
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/sb-members.c b/fs/bcachefs/sb-members.c
index 0573c7b00151..e3c73d903898 100644
--- a/fs/bcachefs/sb-members.c
+++ b/fs/bcachefs/sb-members.c
@@ -68,34 +68,13 @@ struct bch_member *bch2_members_v2_get_mut(struct bch_sb *sb, int i)
return __bch2_members_v2_get_mut(bch2_sb_field_get(sb, members_v2), i);
}
-static struct bch_member members_v2_get(struct bch_sb_field_members_v2 *mi, int i)
-{
- struct bch_member ret, *p = __bch2_members_v2_get_mut(mi, i);
- memset(&ret, 0, sizeof(ret));
- memcpy(&ret, p, min_t(size_t, le16_to_cpu(mi->member_bytes), sizeof(ret)));
- return ret;
-}
-
-static struct bch_member *members_v1_get_mut(struct bch_sb_field_members_v1 *mi, int i)
-{
- return (void *) mi->_members + (i * BCH_MEMBER_V1_BYTES);
-}
-
-static struct bch_member members_v1_get(struct bch_sb_field_members_v1 *mi, int i)
-{
- struct bch_member ret, *p = members_v1_get_mut(mi, i);
- memset(&ret, 0, sizeof(ret));
- memcpy(&ret, p, min_t(size_t, BCH_MEMBER_V1_BYTES, sizeof(ret)));
- return ret;
-}
-
struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i)
{
struct bch_sb_field_members_v2 *mi2 = bch2_sb_field_get(sb, members_v2);
if (mi2)
- return members_v2_get(mi2, i);
+ return bch2_members_v2_get(mi2, i);
struct bch_sb_field_members_v1 *mi1 = bch2_sb_field_get(sb, members_v1);
- return members_v1_get(mi1, i);
+ return bch2_members_v1_get(mi1, i);
}
static int sb_members_v2_resize_entries(struct bch_fs *c)
@@ -211,33 +190,25 @@ static int validate_member(struct printbuf *err,
return 0;
}
-static void member_to_text(struct printbuf *out,
- struct bch_member m,
- struct bch_sb_field_disk_groups *gi,
- struct bch_sb *sb,
- int i)
+void bch2_member_to_text(struct printbuf *out,
+ struct bch_member *m,
+ struct bch_sb_field_disk_groups *gi,
+ struct bch_sb *sb,
+ unsigned idx)
{
- unsigned data_have = bch2_sb_dev_has_data(sb, i);
- u64 bucket_size = le16_to_cpu(m.bucket_size);
- u64 device_size = le64_to_cpu(m.nbuckets) * bucket_size;
-
- if (!bch2_member_alive(&m))
- return;
-
- prt_printf(out, "Device:\t%u\n", i);
-
- printbuf_indent_add(out, 2);
+ u64 bucket_size = le16_to_cpu(m->bucket_size);
+ u64 device_size = le64_to_cpu(m->nbuckets) * bucket_size;
prt_printf(out, "Label:\t");
- if (BCH_MEMBER_GROUP(&m))
+ if (BCH_MEMBER_GROUP(m))
bch2_disk_path_to_text_sb(out, sb,
- BCH_MEMBER_GROUP(&m) - 1);
+ BCH_MEMBER_GROUP(m) - 1);
else
prt_printf(out, "(none)");
prt_newline(out);
prt_printf(out, "UUID:\t");
- pr_uuid(out, m.uuid.b);
+ pr_uuid(out, m->uuid.b);
prt_newline(out);
prt_printf(out, "Size:\t");
@@ -245,40 +216,41 @@ static void member_to_text(struct printbuf *out,
prt_newline(out);
for (unsigned i = 0; i < BCH_MEMBER_ERROR_NR; i++)
- prt_printf(out, "%s errors:\t%llu\n", bch2_member_error_strs[i], le64_to_cpu(m.errors[i]));
+ prt_printf(out, "%s errors:\t%llu\n", bch2_member_error_strs[i], le64_to_cpu(m->errors[i]));
for (unsigned i = 0; i < BCH_IOPS_NR; i++)
- prt_printf(out, "%s iops:\t%u\n", bch2_iops_measurements[i], le32_to_cpu(m.iops[i]));
+ prt_printf(out, "%s iops:\t%u\n", bch2_iops_measurements[i], le32_to_cpu(m->iops[i]));
prt_printf(out, "Bucket size:\t");
prt_units_u64(out, bucket_size << 9);
prt_newline(out);
- prt_printf(out, "First bucket:\t%u\n", le16_to_cpu(m.first_bucket));
- prt_printf(out, "Buckets:\t%llu\n", le64_to_cpu(m.nbuckets));
+ prt_printf(out, "First bucket:\t%u\n", le16_to_cpu(m->first_bucket));
+ prt_printf(out, "Buckets:\t%llu\n", le64_to_cpu(m->nbuckets));
prt_printf(out, "Last mount:\t");
- if (m.last_mount)
- bch2_prt_datetime(out, le64_to_cpu(m.last_mount));
+ if (m->last_mount)
+ bch2_prt_datetime(out, le64_to_cpu(m->last_mount));
else
prt_printf(out, "(never)");
prt_newline(out);
- prt_printf(out, "Last superblock write:\t%llu\n", le64_to_cpu(m.seq));
+ prt_printf(out, "Last superblock write:\t%llu\n", le64_to_cpu(m->seq));
prt_printf(out, "State:\t%s\n",
- BCH_MEMBER_STATE(&m) < BCH_MEMBER_STATE_NR
- ? bch2_member_states[BCH_MEMBER_STATE(&m)]
+ BCH_MEMBER_STATE(m) < BCH_MEMBER_STATE_NR
+ ? bch2_member_states[BCH_MEMBER_STATE(m)]
: "unknown");
prt_printf(out, "Data allowed:\t");
- if (BCH_MEMBER_DATA_ALLOWED(&m))
- prt_bitflags(out, __bch2_data_types, BCH_MEMBER_DATA_ALLOWED(&m));
+ if (BCH_MEMBER_DATA_ALLOWED(m))
+ prt_bitflags(out, __bch2_data_types, BCH_MEMBER_DATA_ALLOWED(m));
else
prt_printf(out, "(none)");
prt_newline(out);
prt_printf(out, "Has data:\t");
+ unsigned data_have = bch2_sb_dev_has_data(sb, idx);
if (data_have)
prt_bitflags(out, __bch2_data_types, data_have);
else
@@ -286,22 +258,36 @@ static void member_to_text(struct printbuf *out,
prt_newline(out);
prt_printf(out, "Btree allocated bitmap blocksize:\t");
- if (m.btree_bitmap_shift < 64)
- prt_units_u64(out, 1ULL << m.btree_bitmap_shift);
+ if (m->btree_bitmap_shift < 64)
+ prt_units_u64(out, 1ULL << m->btree_bitmap_shift);
else
- prt_printf(out, "(invalid shift %u)", m.btree_bitmap_shift);
+ prt_printf(out, "(invalid shift %u)", m->btree_bitmap_shift);
prt_newline(out);
prt_printf(out, "Btree allocated bitmap:\t");
- bch2_prt_u64_base2_nbits(out, le64_to_cpu(m.btree_allocated_bitmap), 64);
+ bch2_prt_u64_base2_nbits(out, le64_to_cpu(m->btree_allocated_bitmap), 64);
prt_newline(out);
- prt_printf(out, "Durability:\t%llu\n", BCH_MEMBER_DURABILITY(&m) ? BCH_MEMBER_DURABILITY(&m) - 1 : 1);
+ prt_printf(out, "Durability:\t%llu\n", BCH_MEMBER_DURABILITY(m) ? BCH_MEMBER_DURABILITY(m) - 1 : 1);
+
+ prt_printf(out, "Discard:\t%llu\n", BCH_MEMBER_DISCARD(m));
+ prt_printf(out, "Freespace initialized:\t%llu\n", BCH_MEMBER_FREESPACE_INITIALIZED(m));
+ prt_printf(out, "Resize on mount:\t%llu\n", BCH_MEMBER_RESIZE_ON_MOUNT(m));
+}
+
+static void member_to_text(struct printbuf *out,
+ struct bch_member m,
+ struct bch_sb_field_disk_groups *gi,
+ struct bch_sb *sb,
+ unsigned idx)
+{
+ if (!bch2_member_alive(&m))
+ return;
- prt_printf(out, "Discard:\t%llu\n", BCH_MEMBER_DISCARD(&m));
- prt_printf(out, "Freespace initialized:\t%llu\n", BCH_MEMBER_FREESPACE_INITIALIZED(&m));
- prt_printf(out, "Resize on mount:\t%llu\n", BCH_MEMBER_RESIZE_ON_MOUNT(&m));
+ prt_printf(out, "Device:\t%u\n", idx);
+ printbuf_indent_add(out, 2);
+ bch2_member_to_text(out, &m, gi, sb, idx);
printbuf_indent_sub(out, 2);
}
@@ -317,7 +303,7 @@ static int bch2_sb_members_v1_validate(struct bch_sb *sb, struct bch_sb_field *f
}
for (i = 0; i < sb->nr_devices; i++) {
- struct bch_member m = members_v1_get(mi, i);
+ struct bch_member m = bch2_members_v1_get(mi, i);
int ret = validate_member(err, m, sb, i);
if (ret)
@@ -343,7 +329,7 @@ static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb,
prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices);
for (unsigned i = 0; i < min(sb->nr_devices, nr); i++)
- member_to_text(out, members_v1_get(mi, i), gi, sb, i);
+ member_to_text(out, bch2_members_v1_get(mi, i), gi, sb, i);
}
const struct bch_sb_field_ops bch_sb_field_ops_members_v1 = {
@@ -377,7 +363,7 @@ static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb,
*/
for (unsigned i = 0; i < min(sb->nr_devices, nr); i++)
- member_to_text(out, members_v2_get(mi, i), gi, sb, i);
+ member_to_text(out, bch2_members_v2_get(mi, i), gi, sb, i);
}
static int bch2_sb_members_v2_validate(struct bch_sb *sb, struct bch_sb_field *f,
@@ -394,7 +380,7 @@ static int bch2_sb_members_v2_validate(struct bch_sb *sb, struct bch_sb_field *f
}
for (unsigned i = 0; i < sb->nr_devices; i++) {
- int ret = validate_member(err, members_v2_get(mi, i), sb, i);
+ int ret = validate_member(err, bch2_members_v2_get(mi, i), sb, i);
if (ret)
return ret;
}
@@ -430,7 +416,7 @@ void bch2_sb_members_to_cpu(struct bch_fs *c)
struct bch_sb_field_members_v2 *mi2 = bch2_sb_field_get(c->disk_sb.sb, members_v2);
if (mi2)
for (unsigned i = 0; i < c->sb.nr_devices; i++) {
- struct bch_member m = members_v2_get(mi2, i);
+ struct bch_member m = bch2_members_v2_get(mi2, i);
bool removed = uuid_equal(&m.uuid, &BCH_SB_MEMBER_DELETED_UUID);
mod_bit(i, c->devs_removed.d, removed);
}
diff --git a/fs/bcachefs/sb-members.h b/fs/bcachefs/sb-members.h
index 35d4ab9b6197..6de999cf71cb 100644
--- a/fs/bcachefs/sb-members.h
+++ b/fs/bcachefs/sb-members.h
@@ -14,11 +14,36 @@ __bch2_members_v2_get_mut(struct bch_sb_field_members_v2 *mi, unsigned i)
return (void *) mi->_members + (i * le16_to_cpu(mi->member_bytes));
}
+static inline struct bch_member bch2_members_v2_get(struct bch_sb_field_members_v2 *mi, int i)
+{
+ struct bch_member ret, *p = __bch2_members_v2_get_mut(mi, i);
+ memset(&ret, 0, sizeof(ret));
+ memcpy(&ret, p, min_t(size_t, le16_to_cpu(mi->member_bytes), sizeof(ret)));
+ return ret;
+}
+
+static inline struct bch_member *members_v1_get_mut(struct bch_sb_field_members_v1 *mi, int i)
+{
+ return (void *) mi->_members + (i * BCH_MEMBER_V1_BYTES);
+}
+
+static inline struct bch_member bch2_members_v1_get(struct bch_sb_field_members_v1 *mi, int i)
+{
+ struct bch_member ret, *p = members_v1_get_mut(mi, i);
+ memset(&ret, 0, sizeof(ret));
+ memcpy(&ret, p, min_t(size_t, BCH_MEMBER_V1_BYTES, sizeof(ret)));
+ return ret;
+}
+
int bch2_sb_members_v2_init(struct bch_fs *c);
int bch2_sb_members_cpy_v2_v1(struct bch_sb_handle *disk_sb);
struct bch_member *bch2_members_v2_get_mut(struct bch_sb *sb, int i);
struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i);
+void bch2_member_to_text(struct printbuf *, struct bch_member *,
+ struct bch_sb_field_disk_groups *,
+ struct bch_sb *, unsigned);
+
static inline bool bch2_dev_is_online(struct bch_dev *ca)
{
return !enumerated_ref_is_zero(&ca->io_ref[READ]);
diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c
index 5a1f81749661..84f987d3a02a 100644
--- a/fs/bcachefs/snapshot.c
+++ b/fs/bcachefs/snapshot.c
@@ -1146,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))
- return ret;
+ return bch_err_throw(c, ENOENT_snapshot);
parent->v.children[i] = cpu_to_le32(child_id);