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: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
1c6fdbd8f2
commit
88c07f7397
@ -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 @@ print:
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user