btrfs-progs: convert: Fix inline file extent creation condition
[platform/upstream/btrfs-progs.git] / check / main.c
index b4ecd5e..5fa09ab 100644 (file)
@@ -43,9 +43,9 @@
 #include "kernel-shared/ulist.h"
 #include "hash.h"
 #include "help.h"
-#include "check/original.h"
-#include "check/lowmem.h"
-#include "check/common.h"
+#include "check/mode-common.h"
+#include "check/mode-original.h"
+#include "check/mode-lowmem.h"
 
 enum task_position {
        TASK_EXTENTS,
@@ -1511,8 +1511,15 @@ static int process_file_extent(struct btrfs_root *root,
                        if (found < num_bytes)
                                rec->some_csum_missing = 1;
                } else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
-                       if (found > 0)
-                               rec->errors |= I_ERR_ODD_CSUM_ITEM;
+                       if (found > 0) {
+                               ret = check_prealloc_extent_written(root->fs_info,
+                                                                   disk_bytenr,
+                                                                   num_bytes);
+                               if (ret < 0)
+                                       return ret;
+                               if (ret == 0)
+                                       rec->errors |= I_ERR_ODD_CSUM_ITEM;
+                       }
                }
        }
        return 0;
@@ -5339,7 +5346,9 @@ static int check_space_cache(struct btrfs_root *root)
                        error += ret;
                } else {
                        ret = load_free_space_cache(root->fs_info, cache);
-                       if (!ret)
+                       if (ret < 0)
+                               error++;
+                       if (ret <= 0)
                                continue;
                }
 
@@ -7638,28 +7647,6 @@ repair_abort:
        return err;
 }
 
-u64 calc_stripe_length(u64 type, u64 length, int num_stripes)
-{
-       u64 stripe_size;
-
-       if (type & BTRFS_BLOCK_GROUP_RAID0) {
-               stripe_size = length;
-               stripe_size /= num_stripes;
-       } else if (type & BTRFS_BLOCK_GROUP_RAID10) {
-               stripe_size = length * 2;
-               stripe_size /= num_stripes;
-       } else if (type & BTRFS_BLOCK_GROUP_RAID5) {
-               stripe_size = length;
-               stripe_size /= (num_stripes - 1);
-       } else if (type & BTRFS_BLOCK_GROUP_RAID6) {
-               stripe_size = length;
-               stripe_size /= (num_stripes - 2);
-       } else {
-               stripe_size = length;
-       }
-       return stripe_size;
-}
-
 /*
  * Check the chunk with its block group/dev list ref:
  * Return 0 if all refs seems valid.
@@ -9054,6 +9041,7 @@ static int build_roots_info_cache(struct btrfs_fs_info *info)
                struct btrfs_key found_key;
                struct btrfs_extent_item *ei;
                struct btrfs_extent_inline_ref *iref;
+               unsigned long item_end;
                int slot = path.slots[0];
                int type;
                u64 flags;
@@ -9082,6 +9070,7 @@ static int build_roots_info_cache(struct btrfs_fs_info *info)
 
                ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
                flags = btrfs_extent_flags(leaf, ei);
+               item_end = (unsigned long)ei + btrfs_item_size_nr(leaf, slot);
 
                if (found_key.type == BTRFS_EXTENT_ITEM_KEY &&
                    !(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK))
@@ -9099,6 +9088,15 @@ static int build_roots_info_cache(struct btrfs_fs_info *info)
                }
 
                /*
+                * It's a valid extent/metadata item that has no inline ref,
+                * but SHARED_BLOCK_REF or other shared references.
+                * So we need to do extra check to avoid reading beyond leaf
+                * boudnary.
+                */
+               if ((unsigned long)iref >= item_end)
+                       goto next;
+
+               /*
                 * For a root extent, it must be of the following type and the
                 * first (and only one) iref in the item.
                 */