diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/bcachefs_format.h | 11 | ||||
-rw-r--r-- | fs/bcachefs/bkey_methods.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/bkey_types.h | 5 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 38 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.c | 72 | ||||
-rw-r--r-- | fs/bcachefs/btree_update.c | 76 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/errcode.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/fs.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/fsck.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/move.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/sb-counters_format.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/sb-errors_format.h | 4 | ||||
-rw-r--r-- | fs/bcachefs/sb-members.c | 116 | ||||
-rw-r--r-- | fs/bcachefs/sb-members.h | 25 | ||||
-rw-r--r-- | fs/bcachefs/snapshot.c | 2 |
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); |