Commit 88c07f73 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Only check inode i_nlink during full fsck

Now that all filesystem operatinos that manipulate the filesystem
heirachy and i_nlink are fully atomic, we can add a feature bit to
indicate i_nlink doesn't need to be checked.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1c6fdbd8
...@@ -472,6 +472,7 @@ enum { ...@@ -472,6 +472,7 @@ enum {
/* misc: */ /* misc: */
BCH_FS_BDEV_MOUNTED, BCH_FS_BDEV_MOUNTED,
BCH_FS_FSCK_FIXED_ERRORS, BCH_FS_FSCK_FIXED_ERRORS,
BCH_FS_FSCK_UNFIXED_ERRORS,
BCH_FS_FIXED_GENS, BCH_FS_FIXED_GENS,
BCH_FS_REBUILD_REPLICAS, BCH_FS_REBUILD_REPLICAS,
BCH_FS_HOLD_BTREE_WRITES, BCH_FS_HOLD_BTREE_WRITES,
......
...@@ -132,8 +132,9 @@ enum fsck_err_ret bch2_fsck_err(struct bch_fs *c, unsigned flags, ...@@ -132,8 +132,9 @@ enum fsck_err_ret bch2_fsck_err(struct bch_fs *c, unsigned flags,
mutex_unlock(&c->fsck_error_lock); mutex_unlock(&c->fsck_error_lock);
if (fix) set_bit(fix
set_bit(BCH_FS_FSCK_FIXED_ERRORS, &c->flags); ? BCH_FS_FSCK_FIXED_ERRORS
: BCH_FS_FSCK_UNFIXED_ERRORS, &c->flags);
return fix ? FSCK_ERR_FIX return fix ? FSCK_ERR_FIX
: flags & FSCK_CAN_IGNORE ? FSCK_ERR_IGNORE : flags & FSCK_CAN_IGNORE ? FSCK_ERR_IGNORE
......
...@@ -954,6 +954,23 @@ static int check_inode_nlink(struct bch_fs *c, ...@@ -954,6 +954,23 @@ static int check_inode_nlink(struct bch_fs *c,
return 0; return 0;
} }
if (!link->count &&
!(u->bi_flags & BCH_INODE_UNLINKED) &&
(c->sb.features & (1 << BCH_FEATURE_ATOMIC_NLINK))) {
if (fsck_err(c, "unreachable inode %llu not marked as unlinked (type %u)",
u->bi_inum, mode_to_type(u->bi_mode)) ==
FSCK_ERR_IGNORE)
return 0;
ret = reattach_inode(c, lostfound_inode, u->bi_inum);
if (ret)
return ret;
link->count = 1;
real_i_nlink = nlink_bias(u->bi_mode) + link->dir_count;
goto set_i_nlink;
}
if (i_nlink < link->count) { if (i_nlink < link->count) {
if (fsck_err(c, "inode %llu i_link too small (%u < %u, type %i)", if (fsck_err(c, "inode %llu i_link too small (%u < %u, type %i)",
u->bi_inum, i_nlink, link->count, u->bi_inum, i_nlink, link->count,
...@@ -973,6 +990,16 @@ static int check_inode_nlink(struct bch_fs *c, ...@@ -973,6 +990,16 @@ static int check_inode_nlink(struct bch_fs *c,
goto set_i_nlink; goto set_i_nlink;
} }
if (i_nlink != real_i_nlink &&
(c->sb.features & (1 << BCH_FEATURE_ATOMIC_NLINK))) {
if (fsck_err(c, "inode %llu has wrong i_nlink "
"(type %u i_nlink %u, should be %u)",
u->bi_inum, mode_to_type(u->bi_mode),
i_nlink, real_i_nlink) == FSCK_ERR_IGNORE)
return 0;
goto set_i_nlink;
}
if (real_i_nlink && i_nlink != real_i_nlink) if (real_i_nlink && i_nlink != real_i_nlink)
bch_verbose(c, "setting inode %llu nlink from %u to %u", bch_verbose(c, "setting inode %llu nlink from %u to %u",
u->bi_inum, i_nlink, real_i_nlink); u->bi_inum, i_nlink, real_i_nlink);
...@@ -1299,7 +1326,8 @@ int bch2_fsck(struct bch_fs *c) ...@@ -1299,7 +1326,8 @@ int bch2_fsck(struct bch_fs *c)
if (!c->opts.nofsck) if (!c->opts.nofsck)
return bch2_fsck_full(c); return bch2_fsck_full(c);
if (!c->sb.clean) if (!c->sb.clean &&
!(c->sb.features & (1 << BCH_FEATURE_ATOMIC_NLINK)))
return bch2_fsck_inode_nlink(c); return bch2_fsck_inode_nlink(c);
return bch2_fsck_walk_inodes_only(c); return bch2_fsck_walk_inodes_only(c);
......
...@@ -256,6 +256,12 @@ int bch2_fs_recovery(struct bch_fs *c) ...@@ -256,6 +256,12 @@ int bch2_fs_recovery(struct bch_fs *c)
if (ret) if (ret)
goto err; goto err;
if (!test_bit(BCH_FS_FSCK_UNFIXED_ERRORS, &c->flags)) {
mutex_lock(&c->sb_lock);
c->disk_sb.sb->features[0] |= 1ULL << BCH_FEATURE_ATOMIC_NLINK;
mutex_unlock(&c->sb_lock);
}
if (enabled_qtypes(c)) { if (enabled_qtypes(c)) {
bch_verbose(c, "reading quotas:"); bch_verbose(c, "reading quotas:");
ret = bch2_fs_quota_read(c); ret = bch2_fs_quota_read(c);
...@@ -366,6 +372,7 @@ int bch2_fs_initialize(struct bch_fs *c) ...@@ -366,6 +372,7 @@ int bch2_fs_initialize(struct bch_fs *c)
mutex_lock(&c->sb_lock); mutex_lock(&c->sb_lock);
SET_BCH_SB_INITIALIZED(c->disk_sb.sb, true); SET_BCH_SB_INITIALIZED(c->disk_sb.sb, true);
SET_BCH_SB_CLEAN(c->disk_sb.sb, false); SET_BCH_SB_CLEAN(c->disk_sb.sb, false);
c->disk_sb.sb->features[0] |= 1ULL << BCH_FEATURE_ATOMIC_NLINK;
bch2_write_super(c); bch2_write_super(c);
mutex_unlock(&c->sb_lock); mutex_unlock(&c->sb_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment