diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-06-25 23:35:49 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:10:05 +0300 |
commit | 06dcca5191dcae948fa8ffd9369deb832881ffcd (patch) | |
tree | 83576b168a0f04e5ffd4706af16404329b6d7e08 /fs/bcachefs/fsck.c | |
parent | 1fa3e87ac50a24a4f6a71986a4d9bc2f16d0667e (diff) | |
download | linux-06dcca5191dcae948fa8ffd9369deb832881ffcd.tar.xz |
bcachefs: fsck: Break walk_inode() up into multiple functions
Some refactoring, prep work for algorithm improvements related to
snapshots.
we need to add a bitmap to the list of inodes for "seen this snapshot";
for this bitmap to correctly be available, we'll need to gather the list
of inodes first, and later look up the inode for a given snapshot.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/fsck.c')
-rw-r--r-- | fs/bcachefs/fsck.c | 103 |
1 files changed, 57 insertions, 46 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index 3503dabe3871..7af65030f9d8 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -639,26 +639,23 @@ static int add_inode(struct bch_fs *c, struct inode_walker *w, })); } -static int __walk_inode(struct btree_trans *trans, - struct inode_walker *w, struct bpos pos) +static int get_inodes_all_snapshots(struct btree_trans *trans, + struct inode_walker *w, u64 inum) { struct bch_fs *c = trans->c; struct btree_iter iter; struct bkey_s_c k; u32 restart_count = trans->restart_count; - unsigned i; int ret; - pos.snapshot = bch2_snapshot_equiv(c, pos.snapshot); - - if (pos.inode == w->cur_inum) - goto lookup_snapshot; + if (w->cur_inum == inum) + return 0; w->inodes.nr = 0; - for_each_btree_key(trans, iter, BTREE_ID_inodes, POS(0, pos.inode), + for_each_btree_key(trans, iter, BTREE_ID_inodes, POS(0, inum), BTREE_ITER_ALL_SNAPSHOTS, k, ret) { - if (k.k->p.offset != pos.inode) + if (k.k->p.offset != inum) break; if (bkey_is_inode(k.k)) @@ -669,40 +666,62 @@ static int __walk_inode(struct btree_trans *trans, if (ret) return ret; - w->cur_inum = pos.inode; + w->cur_inum = inum; w->first_this_inode = true; if (trans_was_restarted(trans, restart_count)) return -BCH_ERR_transaction_restart_nested; -lookup_snapshot: - for (i = 0; i < w->inodes.nr; i++) - if (bch2_snapshot_is_ancestor(c, pos.snapshot, w->inodes.data[i].snapshot)) + return 0; +} + +static struct inode_walker_entry * +lookup_inode_for_snapshot(struct bch_fs *c, + struct inode_walker *w, u32 snapshot) +{ + struct inode_walker_entry *i; + + snapshot = bch2_snapshot_equiv(c, snapshot); + + darray_for_each(w->inodes, i) + if (bch2_snapshot_is_ancestor(c, snapshot, i->snapshot)) goto found; - return INT_MAX; + + return NULL; found: - BUG_ON(pos.snapshot > w->inodes.data[i].snapshot); + BUG_ON(snapshot > i->snapshot); - if (pos.snapshot != w->inodes.data[i].snapshot) { - struct inode_walker_entry e = w->inodes.data[i]; + if (snapshot != i->snapshot) { + struct inode_walker_entry new = *i; + int ret; - e.snapshot = pos.snapshot; - e.count = 0; + new.snapshot = snapshot; + new.count = 0; bch_info(c, "have key for inode %llu:%u but have inode in ancestor snapshot %u", - pos.inode, pos.snapshot, w->inodes.data[i].snapshot); + w->cur_inum, snapshot, i->snapshot); - while (i && w->inodes.data[i - 1].snapshot > pos.snapshot) + while (i > w->inodes.data && i[-1].snapshot > snapshot) --i; - ret = darray_insert_item(&w->inodes, i, e); + ret = darray_insert_item(&w->inodes, i - w->inodes.data, new); if (ret) - return ret; + return ERR_PTR(ret); } return i; } +static struct inode_walker_entry *walk_inode(struct btree_trans *trans, + struct inode_walker *w, struct bpos pos) +{ + int ret = get_inodes_all_snapshots(trans, w, pos.inode); + if (ret) + return ERR_PTR(ret); + + return lookup_inode_for_snapshot(trans->c, w, pos.snapshot); +} + static int __get_visible_inodes(struct btree_trans *trans, struct inode_walker *w, struct snapshots_seen *s, @@ -1300,11 +1319,12 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter, if (ret) goto err; - ret = __walk_inode(trans, inode, equiv); - if (ret < 0) + i = walk_inode(trans, inode, equiv); + ret = PTR_ERR_OR_ZERO(i); + if (ret) goto err; - if (fsck_err_on(ret == INT_MAX, c, + if (fsck_err_on(!i, c, "extent in missing inode:\n %s", (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { @@ -1313,13 +1333,8 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter, goto out; } - if (ret == INT_MAX) { - ret = 0; + if (!i) goto out; - } - - i = inode->inodes.data + ret; - ret = 0; if (fsck_err_on(!S_ISREG(i->inode.bi_mode) && !S_ISLNK(i->inode.bi_mode), c, @@ -1625,7 +1640,8 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, BUG_ON(!iter->path->should_be_locked); - ret = __walk_inode(trans, dir, equiv); + i = walk_inode(trans, dir, equiv); + ret = PTR_ERR_OR_ZERO(i); if (ret < 0) goto err; @@ -1633,7 +1649,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, *hash_info = bch2_hash_info_init(c, &dir->inodes.data[0].inode); dir->first_this_inode = false; - if (fsck_err_on(ret == INT_MAX, c, + if (fsck_err_on(!i, c, "dirent in nonexisting directory:\n%s", (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { @@ -1642,13 +1658,8 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, goto out; } - if (ret == INT_MAX) { - ret = 0; + if (!i) goto out; - } - - i = dir->inodes.data + ret; - ret = 0; if (fsck_err_on(!S_ISDIR(i->inode.bi_mode), c, "dirent in non directory inode type %s:\n%s", @@ -1802,30 +1813,30 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter, struct inode_walker *inode) { struct bch_fs *c = trans->c; + struct inode_walker_entry *i; int ret; ret = check_key_has_snapshot(trans, iter, k); if (ret) return ret; - ret = __walk_inode(trans, inode, k.k->p); - if (ret < 0) + i = walk_inode(trans, inode, k.k->p); + ret = PTR_ERR_OR_ZERO(i); + if (ret) return ret; if (inode->first_this_inode) *hash_info = bch2_hash_info_init(c, &inode->inodes.data[0].inode); inode->first_this_inode = false; - if (fsck_err_on(ret == INT_MAX, c, + if (fsck_err_on(!i, c, "xattr for missing inode %llu", k.k->p.inode)) return bch2_btree_delete_at(trans, iter, 0); - if (ret == INT_MAX) + if (!i) return 0; - ret = 0; - ret = hash_check_key(trans, bch2_xattr_hash_desc, hash_info, iter, k); fsck_err: if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart)) |