Skip to content

Commit ad4c6f3

Browse files
fdmananakdave
authored andcommitted
btrfs: cache if we are using free space bitmaps for a block group
Every time we add free space to the free space tree or we remove free space from the free space tree, we do a lookup for the block group's free space info item in the free space tree. This takes time, navigating the btree and we may block either on IO when reading extent buffers from disk or on extent buffer lock contention due to concurrency. Instead of doing this lookup every time, cache the result in the block structure and use it after the first lookup. This adds two boolean members to the block group structure but doesn't increase the structure's size. The following script that runs fs_mark was used to measure the time spent on run_delayed_tree_ref(), since down that call chain we have calls to add and remove free space to/from the free space tree (calls to btrfs_add_to_free_space_tree() and btrfs_remove_from_free_space_tree()): $ cat test.sh #!/bin/bash DEV=/dev/nullb0 MNT=/mnt FILES=100000 THREADS=$(nproc --all) echo "performance" | \ tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor umount $DEV &> /dev/null mkfs.btrfs -f $DEV mount -o ssd $DEV $MNT OPTS="-S 0 -L 5 -n $FILES -s 0 -t $THREADS -k" for ((i = 1; i <= $THREADS; i++)); do OPTS="$OPTS -d $MNT/d$i" done fs_mark $OPTS umount $MNT This is a heavy metadata test as it's exercising only file creation, so a lot of allocations of metadata extents, creating delayed refs for adding new metadata extents and dropping existing ones due to COW. The results of the times it took to execute run_delayed_tree_ref(), in nanoseconds, are the following. Before this change: Range: 1868.000 - 6482857.000; Mean: 10231.430; Median: 7005.000; Stddev: 27993.173 Percentiles: 90th: 13342.000; 95th: 23279.000; 99th: 82448.000 1868.000 - 4222.038: 270696 ############ 4222.038 - 9541.029: 1201327 ##################################################### 9541.029 - 21559.383: 385436 ################# 21559.383 - 48715.063: 64942 ### 48715.063 - 110073.800: 31454 # 110073.800 - 248714.944: 8218 | 248714.944 - 561977.042: 1030 | 561977.042 - 1269798.254: 295 | 1269798.254 - 2869132.711: 116 | 2869132.711 - 6482857.000: 28 | After this change: Range: 1554.000 - 4557014.000; Mean: 9168.164; Median: 6391.000; Stddev: 21467.060 Percentiles: 90th: 12478.000; 95th: 20964.000; 99th: 72234.000 1554.000 - 3453.820: 219004 ############ 3453.820 - 7674.743: 980645 ##################################################### 7674.743 - 17052.574: 552486 ############################## 17052.574 - 37887.762: 68558 #### 37887.762 - 84178.322: 31557 ## 84178.322 - 187024.331: 12102 # 187024.331 - 415522.355: 1364 | 415522.355 - 923187.626: 256 | 923187.626 - 2051092.468: 125 | 2051092.468 - 4557014.000: 21 | Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent eac901d commit ad4c6f3

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

fs/btrfs/block-group.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ struct btrfs_block_group {
246246
/* Lock for free space tree operations. */
247247
struct mutex free_space_lock;
248248

249+
/* Protected by @free_space_lock. */
250+
bool using_free_space_bitmaps;
251+
/* Protected by @free_space_lock. */
252+
bool using_free_space_bitmaps_cached;
253+
249254
/*
250255
* Number of extents in this block group used for swap files.
251256
* All accesses protected by the spinlock 'lock'.

fs/btrfs/free-space-tree.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ int btrfs_convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
287287
leaf = path->nodes[0];
288288
flags = btrfs_free_space_flags(leaf, info);
289289
flags |= BTRFS_FREE_SPACE_USING_BITMAPS;
290+
block_group->using_free_space_bitmaps = true;
291+
block_group->using_free_space_bitmaps_cached = true;
290292
btrfs_set_free_space_flags(leaf, info, flags);
291293
expected_extent_count = btrfs_free_space_extent_count(leaf, info);
292294
btrfs_release_path(path);
@@ -434,6 +436,8 @@ int btrfs_convert_free_space_to_extents(struct btrfs_trans_handle *trans,
434436
leaf = path->nodes[0];
435437
flags = btrfs_free_space_flags(leaf, info);
436438
flags &= ~BTRFS_FREE_SPACE_USING_BITMAPS;
439+
block_group->using_free_space_bitmaps = false;
440+
block_group->using_free_space_bitmaps_cached = true;
437441
btrfs_set_free_space_flags(leaf, info, flags);
438442
expected_extent_count = btrfs_free_space_extent_count(leaf, info);
439443
btrfs_release_path(path);
@@ -796,13 +800,19 @@ static int using_bitmaps(struct btrfs_block_group *bg, struct btrfs_path *path)
796800
struct btrfs_free_space_info *info;
797801
u32 flags;
798802

803+
if (bg->using_free_space_bitmaps_cached)
804+
return bg->using_free_space_bitmaps;
805+
799806
info = btrfs_search_free_space_info(NULL, bg, path, 0);
800807
if (IS_ERR(info))
801808
return PTR_ERR(info);
802809
flags = btrfs_free_space_flags(path->nodes[0], info);
803810
btrfs_release_path(path);
804811

805-
return (flags & BTRFS_FREE_SPACE_USING_BITMAPS) ? 1 : 0;
812+
bg->using_free_space_bitmaps = (flags & BTRFS_FREE_SPACE_USING_BITMAPS);
813+
bg->using_free_space_bitmaps_cached = true;
814+
815+
return bg->using_free_space_bitmaps;
806816
}
807817

808818
EXPORT_FOR_TESTS

0 commit comments

Comments
 (0)