diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-04-09 03:25:37 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:00 -0400 |
commit | 176cf4bf59014d03be6cef33cabb677d2117dbb2 (patch) | |
tree | 0c2c7a2dba2f37435f8ea34c03bb779d79bfd2a9 /fs | |
parent | b69ac13cb39176634f1dd924dfabe2e282615d41 (diff) |
bcachefs: Fix fsck to not use bch2_link_trans()
bch2_link_trans() uses the btree key cache for inode updates, and fsck
isn't supposed to - also, it's not really what we want for reattaching
unreachable inodes anyways.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/fsck.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index 6bc3f2f09e36..d7d26fb40432 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -128,22 +128,63 @@ static int remove_dirent(struct btree_trans *trans, __remove_dirent(trans, dirent)); } -static int reattach_inode(struct bch_fs *c, - struct bch_inode_unpacked *lostfound_inode, - u64 inum) +static int __reattach_inode(struct btree_trans *trans, + struct bch_inode_unpacked *lostfound, + u64 inum) { - struct bch_inode_unpacked dir_u, inode_u; + struct bch_hash_info dir_hash = + bch2_hash_info_init(trans->c, lostfound); + struct btree_iter *dir_iter = NULL, *inode_iter = NULL; + struct bch_inode_unpacked inode_u; char name_buf[20]; struct qstr name; + u64 dir_offset = 0; int ret; snprintf(name_buf, sizeof(name_buf), "%llu", inum); name = (struct qstr) QSTR(name_buf); - ret = bch2_trans_do(c, NULL, NULL, - BTREE_INSERT_LAZY_RW, - bch2_link_trans(&trans, lostfound_inode->bi_inum, - inum, &dir_u, &inode_u, &name)); + inode_iter = bch2_inode_peek(trans, &inode_u, inum, 0); + ret = PTR_ERR_OR_ZERO(inode_iter); + if (ret) + goto err; + + if (S_ISDIR(inode_u.bi_mode)) { + lostfound->bi_nlink++; + + ret = write_inode(trans, lostfound, U32_MAX); + if (ret) + goto err; + } + + ret = bch2_dirent_create(trans, lostfound->bi_inum, &dir_hash, + mode_to_type(inode_u.bi_mode), + &name, inum, &dir_offset, + BCH_HASH_SET_MUST_CREATE); + if (ret) + goto err; + + inode_u.bi_dir = lostfound->bi_inum; + inode_u.bi_dir_offset = dir_offset; + + ret = write_inode(trans, &inode_u, U32_MAX); + if (ret) + goto err; +err: + bch2_trans_iter_put(trans, dir_iter); + bch2_trans_iter_put(trans, inode_iter); + return ret; +} + +static int reattach_inode(struct btree_trans *trans, + struct bch_inode_unpacked *lostfound, + u64 inum) +{ + struct bch_fs *c = trans->c; + int ret; + + ret = __bch2_trans_do(trans, NULL, NULL, BTREE_INSERT_LAZY_RW, + __reattach_inode(trans, lostfound, inum)); if (ret) bch_err(c, "error %i reattaching inode %llu", ret, inum); @@ -1105,9 +1146,7 @@ retry: if (fsck_err_on(!inode_bitmap_test(&dirs_done, k.k->p.offset), c, "unreachable directory found (inum %llu)", k.k->p.offset)) { - bch2_trans_unlock(&trans); - - ret = reattach_inode(c, lostfound_inode, k.k->p.offset); + ret = reattach_inode(&trans, lostfound_inode, k.k->p.offset); if (ret) { goto err; } @@ -1227,7 +1266,7 @@ static int check_inode_nlink(struct btree_trans *trans, if (fsck_err_on(!nlink, c, "unreachable inode %llu not marked as unlinked (type %u)", u.bi_inum, mode_to_type(u.bi_mode))) { - ret = reattach_inode(c, lostfound_inode, u.bi_inum); + ret = reattach_inode(trans, lostfound_inode, u.bi_inum); if (ret) return ret; |