In auto/preen mode, let's trigger repairing if filesystem was forced
to stop.

Signed-off-by: Chao Yu <[email protected]>
---
 fsck/fsck.c       |  7 +++++++
 fsck/fsck.h       |  1 +
 fsck/mount.c      | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 include/f2fs_fs.h | 19 ++++++++++++++++++-
 4 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 2f6cc72..db14859 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -3351,6 +3351,7 @@ int fsck_verify(struct f2fs_sb_info *sbi)
        /* fix global metadata */
        if (force || (c.fix_on && f2fs_dev_is_writable())) {
                struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
+               struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
 
                if (force || c.bug_on || c.bug_nat_bits || c.quota_fixed) {
                        /* flush nats to write_nit_bits below */
@@ -3366,6 +3367,12 @@ int fsck_verify(struct f2fs_sb_info *sbi)
                        is_set_ckpt_flags(cp, CP_QUOTA_NEED_FSCK_FLAG)) {
                        write_checkpoints(sbi);
                }
+
+               if (c.abnormal_stop) {
+                       memset(sb->s_stop_reason, 0, MAX_STOP_REASON);
+                       update_superblock(sb, SB_MASK_ALL);
+               }
+
                /* to return FSCK_ERROR_CORRECTED */
                ret = 0;
        }
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 8234986..6f0b019 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -237,6 +237,7 @@ extern void update_data_blkaddr(struct f2fs_sb_info *, 
nid_t, u16, block_t);
 extern void update_nat_blkaddr(struct f2fs_sb_info *, nid_t, nid_t, block_t);
 
 extern void print_raw_sb_info(struct f2fs_super_block *);
+extern bool is_checkpoint_stop(struct f2fs_super_block *, bool);
 extern pgoff_t current_nat_addr(struct f2fs_sb_info *, nid_t, int *);
 
 extern u32 get_free_segments(struct f2fs_sb_info *);
diff --git a/fsck/mount.c b/fsck/mount.c
index aebe363..6b21625 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -583,6 +583,34 @@ void print_sb_state(struct f2fs_super_block *sb)
        MSG(0, "\n");
 }
 
+static char *stop_reason_str[] = {
+       [STOP_CP_REASON_SHUTDOWN]               = "shutdown",
+       [STOP_CP_REASON_FAULT_INJECT]           = "fault_inject",
+       [STOP_CP_REASON_META_PAGE]              = "meta_page",
+       [STOP_CP_REASON_WRITE_FAIL]             = "write_fail",
+       [STOP_CP_REASON_CORRUPTED_SUMMARY]      = "corrupted_summary",
+       [STOP_CP_REASON_UPDATE_INODE]           = "update_inode",
+       [STOP_CP_REASON_FLUSH_FAIL]             = "flush_fail",
+};
+
+void print_sb_stop_reason(struct f2fs_super_block *sb)
+{
+       u8 *reason = sb->s_stop_reason;
+       int i;
+
+       if (!c.force_stop)
+               return;
+
+       MSG(0, "Info: checkpoint stop reason: ");
+
+       for (i = 0; i < STOP_CP_REASON_MAX; i++) {
+               if (reason[i])
+                       MSG(0, "%s(%d) ", stop_reason_str[i], reason[i]);
+       }
+
+       MSG(0, "\n");
+}
+
 bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
                                        block_t blkaddr, int type)
 {
@@ -966,10 +994,14 @@ int validate_super_block(struct f2fs_sb_info *sbi, enum 
SB_ADDR sb_addr)
                                VERSION_NAME_LEN);
                get_kernel_version(c.init_version);
 
+               c.force_stop = is_checkpoint_stop(sbi->raw_super, false);
+               c.abnormal_stop = is_checkpoint_stop(sbi->raw_super, true);
+
                MSG(0, "Info: MKFS version\n  \"%s\"\n", c.init_version);
                MSG(0, "Info: FSCK version\n  from \"%s\"\n    to \"%s\"\n",
                                        c.sb_version, c.version);
                print_sb_state(sbi->raw_super);
+               print_sb_stop_reason(sbi->raw_super);
                return 0;
        }
 
@@ -1201,6 +1233,20 @@ fail_no_cp:
        return -EINVAL;
 }
 
+bool is_checkpoint_stop(struct f2fs_super_block *sb, bool abnormal)
+{
+       int i;
+
+       for (i = 0; i < STOP_CP_REASON_MAX; i++) {
+               if (abnormal && i == STOP_CP_REASON_SHUTDOWN)
+                       continue;
+               if (sb->s_stop_reason[i])
+                       return true;
+       }
+
+       return false;
+}
+
 /*
  * For a return value of 1, caller should further check for c.fix_on state
  * and take appropriate action.
@@ -1210,6 +1256,7 @@ static int f2fs_should_proceed(struct f2fs_super_block 
*sb, u32 flag)
        if (!c.fix_on && (c.auto_fix || c.preen_mode)) {
                if (flag & CP_FSCK_FLAG ||
                        flag & CP_QUOTA_NEED_FSCK_FLAG ||
+                       c.abnormal_stop ||
                        (exist_qf_ino(sb) && (flag & CP_ERROR_FLAG))) {
                        c.fix_on = 1;
                } else if (!c.preen_mode) {
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index c36c623..424eaad 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -508,6 +508,8 @@ struct f2fs_configuration {
        int force;
        int defset;
        int bug_on;
+       int force_stop;
+       int abnormal_stop;
        int bug_nat_bits;
        bool quota_fixed;
        int alloc_failed;
@@ -757,6 +759,20 @@ struct f2fs_device {
 
 static_assert(sizeof(struct f2fs_device) == 68, "");
 
+/* reason of stop_checkpoint */
+enum stop_cp_reason {
+       STOP_CP_REASON_SHUTDOWN,
+       STOP_CP_REASON_FAULT_INJECT,
+       STOP_CP_REASON_META_PAGE,
+       STOP_CP_REASON_WRITE_FAIL,
+       STOP_CP_REASON_CORRUPTED_SUMMARY,
+       STOP_CP_REASON_UPDATE_INODE,
+       STOP_CP_REASON_FLUSH_FAIL,
+       STOP_CP_REASON_MAX,
+};
+
+#define        MAX_STOP_REASON                 32
+
 struct f2fs_super_block {
        __le32 magic;                   /* Magic Number */
        __le16 major_ver;               /* Major Version */
@@ -801,7 +817,8 @@ struct f2fs_super_block {
        __u8 hot_ext_count;             /* # of hot file extension */
        __le16  s_encoding;             /* Filename charset encoding */
        __le16  s_encoding_flags;       /* Filename charset encoding flags */
-       __u8 reserved[306];             /* valid reserved region */
+       __u8 s_stop_reason[MAX_STOP_REASON];    /* stop checkpoint reason */
+       __u8 reserved[274];             /* valid reserved region */
        __le32 crc;                     /* checksum of superblock */
 };
 
-- 
2.36.1



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to