btrfs: precalculate checksums per leaf once
authorDavid Sterba <dsterba@suse.com>
Thu, 2 Jul 2020 08:54:11 +0000 (10:54 +0200)
committerDavid Sterba <dsterba@suse.com>
Tue, 8 Dec 2020 14:53:58 +0000 (15:53 +0100)
btrfs_csum_bytes_to_leaves shows up in system profiles, which makes it a
candidate for optimizations. After the 64bit division has been replaced
by shift, there's still a calculation done each time the function is
called: checksums per leaf.

As this is a constant value for the entire filesystem lifetime, we
can calculate it once at mount time and reuse. This also allows to
reduce the division to 64bit/32bit as we know the constant will always
fit the 32bit type.

Replace the open-coded rounding up with a macro that internally handles
the 64bit division and as it's now a short function, make it static
inline (slight code increase, slight stack usage reduction).

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c

index 3d06596b8746841b4dbe9373bf83d6ffb1fa49d9..f28960647c0144f6464b927d693ce6493eb8ba5c 100644 (file)
@@ -938,6 +938,7 @@ struct btrfs_fs_info {
        /* ilog2 of sectorsize, use to avoid 64bit division */
        u32 sectorsize_bits;
        u32 csum_size;
+       u32 csums_per_leaf;
        u32 stripesize;
 
        /* Block groups and devices containing active swapfiles. */
@@ -2525,7 +2526,17 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
                                     enum btrfs_inline_ref_type is_data);
 u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset);
 
-u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes);
+/*
+ * Take the number of bytes to be checksummmed and figure out how many leaves
+ * it would require to store the csums for that many bytes.
+ */
+static inline u64 btrfs_csum_bytes_to_leaves(
+                       const struct btrfs_fs_info *fs_info, u64 csum_bytes)
+{
+       const u64 num_csums = csum_bytes >> fs_info->sectorsize_bits;
+
+       return DIV_ROUND_UP_ULL(num_csums, fs_info->csums_per_leaf);
+}
 
 /*
  * Use this if we would be adding new items, as we could split nodes as we cow
index 475bd197c4825a740838f1e79356f224445bc530..0e540ddd7d990f2c7c36678ad0e2c9ad60c288e0 100644 (file)
@@ -3081,6 +3081,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
        fs_info->sectorsize = sectorsize;
        fs_info->sectorsize_bits = ilog2(sectorsize);
        fs_info->csum_size = btrfs_super_csum_size(disk_super);
+       fs_info->csums_per_leaf = BTRFS_MAX_ITEM_SIZE(fs_info) / fs_info->csum_size;
        fs_info->stripesize = stripesize;
 
        /*
index 14d5aaa2839963402ee131417dc2203f7e245f1a..a27caa47aa62382d227d7de59cad7cd0ccba8f14 100644 (file)
@@ -2132,25 +2132,6 @@ static u64 find_middle(struct rb_root *root)
 }
 #endif
 
-/*
- * Takes the number of bytes to be csumm'ed and figures out how many leaves it
- * would require to store the csums for that many bytes.
- */
-u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes)
-{
-       u64 csum_size;
-       u64 num_csums_per_leaf;
-       u64 num_csums;
-
-       csum_size = BTRFS_MAX_ITEM_SIZE(fs_info);
-       num_csums_per_leaf = div64_u64(csum_size,
-                       (u64)btrfs_super_csum_size(fs_info->super_copy));
-       num_csums = csum_bytes >> fs_info->sectorsize_bits;
-       num_csums += num_csums_per_leaf - 1;
-       num_csums = div64_u64(num_csums, num_csums_per_leaf);
-       return num_csums;
-}
-
 /*
  * this starts processing the delayed reference count updates and
  * extent insertions we have queued up so far.  count can be