bcachefs: Only check inode i_nlink during full fsck
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 15 Jul 2018 01:06:51 +0000 (21:06 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:07 +0000 (17:08 -0400)
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>
fs/bcachefs/bcachefs.h
fs/bcachefs/error.c
fs/bcachefs/fsck.c
fs/bcachefs/recovery.c

index b5e119d..57132c7 100644 (file)
@@ -472,6 +472,7 @@ enum {
        /* misc: */
        BCH_FS_BDEV_MOUNTED,
        BCH_FS_FSCK_FIXED_ERRORS,
+       BCH_FS_FSCK_UNFIXED_ERRORS,
        BCH_FS_FIXED_GENS,
        BCH_FS_REBUILD_REPLICAS,
        BCH_FS_HOLD_BTREE_WRITES,
index e975fab..08e7916 100644 (file)
@@ -132,8 +132,9 @@ print:
 
        mutex_unlock(&c->fsck_error_lock);
 
-       if (fix)
-               set_bit(BCH_FS_FSCK_FIXED_ERRORS, &c->flags);
+       set_bit(fix
+               ? BCH_FS_FSCK_FIXED_ERRORS
+               : BCH_FS_FSCK_UNFIXED_ERRORS, &c->flags);
 
        return fix                              ? FSCK_ERR_FIX
                : flags & FSCK_CAN_IGNORE       ? FSCK_ERR_IGNORE
index eb01284..c352fa0 100644 (file)
@@ -954,6 +954,23 @@ static int check_inode_nlink(struct bch_fs *c,
                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 (fsck_err(c, "inode %llu i_link too small (%u < %u, type %i)",
                             u->bi_inum, i_nlink, link->count,
@@ -973,6 +990,16 @@ static int check_inode_nlink(struct bch_fs *c,
                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)
                bch_verbose(c, "setting inode %llu nlink from %u to %u",
                            u->bi_inum, i_nlink, real_i_nlink);
@@ -1299,7 +1326,8 @@ int bch2_fsck(struct bch_fs *c)
        if (!c->opts.nofsck)
                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_walk_inodes_only(c);
index 2596c3c..624d97d 100644 (file)
@@ -256,6 +256,12 @@ int bch2_fs_recovery(struct bch_fs *c)
        if (ret)
                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)) {
                bch_verbose(c, "reading quotas:");
                ret = bch2_fs_quota_read(c);
@@ -366,6 +372,7 @@ int bch2_fs_initialize(struct bch_fs *c)
        mutex_lock(&c->sb_lock);
        SET_BCH_SB_INITIALIZED(c->disk_sb.sb, true);
        SET_BCH_SB_CLEAN(c->disk_sb.sb, false);
+       c->disk_sb.sb->features[0] |= 1ULL << BCH_FEATURE_ATOMIC_NLINK;
 
        bch2_write_super(c);
        mutex_unlock(&c->sb_lock);