f2fs: fix to account compressed blocks in f2fs_compressed_blocks()
authorChao Yu <yuchao0@huawei.com>
Thu, 12 Mar 2020 02:45:29 +0000 (10:45 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Mon, 23 Mar 2020 04:16:29 +0000 (21:16 -0700)
por_fsstress reports inconsistent status in orphan inode, the root cause
of this is in f2fs_write_raw_pages() we decrease i_compr_blocks incorrectly
due to wrong calculation in f2fs_compressed_blocks().

So this patch exposes below two functions based on __f2fs_cluster_blocks:
- f2fs_compressed_blocks: get count of compressed blocks in compressed cluster
- f2fs_cluster_blocks: get count of valid blocks (including reserved blocks)
in compressed cluster.

Then use f2fs_compress_blocks() to get correct compressed blocks count in
f2fs_write_raw_pages().

sanity_check_inode: inode (ino=ad80) hash inconsistent i_compr_blocks:2, i_blocks:1, run fsck to fix

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

index bd3ea01db4486fa0e339ddf78418de71d397a515..f9cf75fe4a12e95919daaf4f17d6dec3cf2851ff 100644 (file)
@@ -535,8 +535,7 @@ static bool __cluster_may_compress(struct compress_ctx *cc)
        return true;
 }
 
-/* return # of compressed block addresses */
-static int f2fs_compressed_blocks(struct compress_ctx *cc)
+static int __f2fs_cluster_blocks(struct compress_ctx *cc, bool compr)
 {
        struct dnode_of_data dn;
        int ret;
@@ -559,8 +558,13 @@ static int f2fs_compressed_blocks(struct compress_ctx *cc)
 
                        blkaddr = data_blkaddr(dn.inode,
                                        dn.node_page, dn.ofs_in_node + i);
-                       if (blkaddr != NULL_ADDR)
-                               ret++;
+                       if (compr) {
+                               if (__is_valid_data_blkaddr(blkaddr))
+                                       ret++;
+                       } else {
+                               if (blkaddr != NULL_ADDR)
+                                       ret++;
+                       }
                }
        }
 fail:
@@ -568,6 +572,18 @@ fail:
        return ret;
 }
 
+/* return # of compressed blocks in compressed cluster */
+static int f2fs_compressed_blocks(struct compress_ctx *cc)
+{
+       return __f2fs_cluster_blocks(cc, true);
+}
+
+/* return # of valid blocks in compressed cluster */
+static int f2fs_cluster_blocks(struct compress_ctx *cc, bool compr)
+{
+       return __f2fs_cluster_blocks(cc, false);
+}
+
 int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index)
 {
        struct compress_ctx cc = {
@@ -577,7 +593,7 @@ int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index)
                .cluster_idx = index >> F2FS_I(inode)->i_log_cluster_size,
        };
 
-       return f2fs_compressed_blocks(&cc);
+       return f2fs_cluster_blocks(&cc, false);
 }
 
 static bool cluster_may_compress(struct compress_ctx *cc)
@@ -626,7 +642,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
        bool prealloc;
 
 retry:
-       ret = f2fs_compressed_blocks(cc);
+       ret = f2fs_cluster_blocks(cc, false);
        if (ret <= 0)
                return ret;