f2fs: compress: do sanity check on cluster when CONFIG_F2FS_CHECK_FS is on
authorChao Yu <chao@kernel.org>
Mon, 28 Aug 2023 14:04:16 +0000 (22:04 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 12 Sep 2023 20:49:33 +0000 (13:49 -0700)
This patch covers sanity check logic on cluster w/ CONFIG_F2FS_CHECK_FS,
otherwise, there will be performance regression while querying cluster
mapping info.

Callers of f2fs_is_compressed_cluster() only care about whether cluster
is compressed or not, rather than # of valid blocks in compressed cluster,
so, let's adjust f2fs_is_compressed_cluster()'s logic according to
caller's requirement.

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/compress.c
fs/f2fs/data.c

index d820801f473e56ab7ea8d66f97c97e95293c4463..0c41647a238168556d734c7aade33b1d08180a8b 100644 (file)
@@ -893,14 +893,15 @@ static bool cluster_has_invalid_data(struct compress_ctx *cc)
 
 bool f2fs_sanity_check_cluster(struct dnode_of_data *dn)
 {
+#ifdef CONFIG_F2FS_CHECK_FS
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
        unsigned int cluster_size = F2FS_I(dn->inode)->i_cluster_size;
-       bool compressed = dn->data_blkaddr == COMPRESS_ADDR;
        int cluster_end = 0;
+       unsigned int count;
        int i;
        char *reason = "";
 
-       if (!compressed)
+       if (dn->data_blkaddr != COMPRESS_ADDR)
                return false;
 
        /* [..., COMPR_ADDR, ...] */
@@ -909,7 +910,7 @@ bool f2fs_sanity_check_cluster(struct dnode_of_data *dn)
                goto out;
        }
 
-       for (i = 1; i < cluster_size; i++) {
+       for (i = 1, count = 1; i < cluster_size; i++, count++) {
                block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
                                                        dn->ofs_in_node + i);
 
@@ -929,19 +930,42 @@ bool f2fs_sanity_check_cluster(struct dnode_of_data *dn)
                        goto out;
                }
        }
+
+       f2fs_bug_on(F2FS_I_SB(dn->inode), count != cluster_size &&
+               !is_inode_flag_set(dn->inode, FI_COMPRESS_RELEASED));
+
        return false;
 out:
        f2fs_warn(sbi, "access invalid cluster, ino:%lu, nid:%u, ofs_in_node:%u, reason:%s",
                        dn->inode->i_ino, dn->nid, dn->ofs_in_node, reason);
        set_sbi_flag(sbi, SBI_NEED_FSCK);
        return true;
+#else
+       return false;
+#endif
+}
+
+static int __f2fs_get_cluster_blocks(struct inode *inode,
+                                       struct dnode_of_data *dn)
+{
+       unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
+       int count, i;
+
+       for (i = 1, count = 1; i < cluster_size; i++) {
+               block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
+                                                       dn->ofs_in_node + i);
+
+               if (__is_valid_data_blkaddr(blkaddr))
+                       count++;
+       }
+
+       return count;
 }
 
 static int __f2fs_cluster_blocks(struct inode *inode,
-                               unsigned int cluster_idx, bool compr)
+                               unsigned int cluster_idx, bool compr_blks)
 {
        struct dnode_of_data dn;
-       unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
        unsigned int start_idx = cluster_idx <<
                                F2FS_I(inode)->i_log_cluster_size;
        int ret;
@@ -956,31 +980,14 @@ static int __f2fs_cluster_blocks(struct inode *inode,
 
        if (f2fs_sanity_check_cluster(&dn)) {
                ret = -EFSCORRUPTED;
-               f2fs_handle_error(F2FS_I_SB(inode), ERROR_CORRUPTED_CLUSTER);
                goto fail;
        }
 
        if (dn.data_blkaddr == COMPRESS_ADDR) {
-               int i;
-
-               ret = 1;
-               for (i = 1; i < cluster_size; i++) {
-                       block_t blkaddr;
-
-                       blkaddr = data_blkaddr(dn.inode,
-                                       dn.node_page, dn.ofs_in_node + i);
-                       if (compr) {
-                               if (__is_valid_data_blkaddr(blkaddr))
-                                       ret++;
-                       } else {
-                               if (blkaddr != NULL_ADDR)
-                                       ret++;
-                       }
-               }
-
-               f2fs_bug_on(F2FS_I_SB(inode),
-                       !compr && ret != cluster_size &&
-                       !is_inode_flag_set(inode, FI_COMPRESS_RELEASED));
+               if (compr_blks)
+                       ret = __f2fs_get_cluster_blocks(inode, &dn);
+               else
+                       ret = 1;
        }
 fail:
        f2fs_put_dnode(&dn);
@@ -993,7 +1000,7 @@ static int f2fs_compressed_blocks(struct compress_ctx *cc)
        return __f2fs_cluster_blocks(cc->inode, cc->cluster_idx, true);
 }
 
-/* return # of valid blocks in compressed cluster */
+/* return whether cluster is compressed one or not */
 int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index)
 {
        return __f2fs_cluster_blocks(inode,
index 1ac34eb49a0e88039094a9224839fb49bab0bcd4..cd9cedc35d7ff87b4f2f01776ef30b6593fc1c6c 100644 (file)
@@ -1690,9 +1690,7 @@ next_block:
                        map->m_flags |= F2FS_MAP_NEW;
        } else if (is_hole) {
                if (f2fs_compressed_file(inode) &&
-                   f2fs_sanity_check_cluster(&dn) &&
-                   (flag != F2FS_GET_BLOCK_FIEMAP ||
-                    IS_ENABLED(CONFIG_F2FS_CHECK_FS))) {
+                   f2fs_sanity_check_cluster(&dn)) {
                        err = -EFSCORRUPTED;
                        f2fs_handle_error(sbi,
                                        ERROR_CORRUPTED_CLUSTER);