From 20d88c17e77ccb7d2dc5762fa978a14dd7d73b18 Mon Sep 17 00:00:00 2001 From: Josef Bacik <josef@toxicpanda.com> Date: Wed, 23 Nov 2022 17:37:25 -0500 Subject: [PATCH] btrfs-progs: move extent cache code directly into btrfs_fs_info We have some extra features in the btrfs-progs copy of the extent_io_tree that don't exist in the kernel. In order to make syncing easier simply move this functionality into btrfs_fs_info, that way we can sync in the new extent_io_tree code and not have to worry about breaking anything. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com> --- kernel-shared/ctree.h | 6 +++- kernel-shared/disk-io.c | 4 +-- kernel-shared/extent_io.c | 76 ++++++++++++++++++++++++++------------- kernel-shared/extent_io.h | 2 ++ 4 files changed, 60 insertions(+), 28 deletions(-) diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 6d5ceec1..5ed92105 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -1217,7 +1217,11 @@ struct btrfs_fs_info { /* the log root tree is a directory of all the other log roots */ struct btrfs_root *log_root_tree; - struct extent_io_tree extent_cache; + struct cache_tree extent_cache; + u64 max_cache_size; + u64 cache_size; + struct list_head lru; + struct extent_io_tree dirty_buffers; struct extent_io_tree free_space_cache; struct extent_io_tree pinned_extents; diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 8c428ade..c266f9c2 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -864,7 +864,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr) !fs_info->block_group_root || !fs_info->super_copy) goto free_all; - extent_io_tree_init(&fs_info->extent_cache); + extent_buffer_init_cache(fs_info); extent_io_tree_init(&fs_info->dirty_buffers); extent_io_tree_init(&fs_info->free_space_cache); extent_io_tree_init(&fs_info->pinned_extents); @@ -1350,7 +1350,7 @@ void btrfs_cleanup_all_caches(struct btrfs_fs_info *fs_info) } free_mapping_cache_tree(&fs_info->mapping_tree.cache_tree); extent_io_tree_cleanup(&fs_info->dirty_buffers); - extent_io_tree_cleanup(&fs_info->extent_cache); + extent_buffer_free_cache(fs_info); extent_io_tree_cleanup(&fs_info->free_space_cache); extent_io_tree_cleanup(&fs_info->pinned_extents); extent_io_tree_cleanup(&fs_info->extent_ins); diff --git a/kernel-shared/extent_io.c b/kernel-shared/extent_io.c index 55d7fe78..d36a32c4 100644 --- a/kernel-shared/extent_io.c +++ b/kernel-shared/extent_io.c @@ -35,13 +35,45 @@ #include "common/device-utils.h" #include "common/internal.h" +static void free_extent_buffer_final(struct extent_buffer *eb); + +void extent_buffer_init_cache(struct btrfs_fs_info *fs_info) +{ + fs_info->max_cache_size = total_memory() / 4; + fs_info->cache_size = 0; + INIT_LIST_HEAD(&fs_info->lru); +} + +void extent_buffer_free_cache(struct btrfs_fs_info *fs_info) +{ + struct extent_buffer *eb; + + while(!list_empty(&fs_info->lru)) { + eb = list_entry(fs_info->lru.next, struct extent_buffer, lru); + if (eb->refs) { + /* + * Reset extent buffer refs to 1, so the + * free_extent_buffer_nocache() can free it for sure. + */ + eb->refs = 1; + fprintf(stderr, + "extent buffer leak: start %llu len %u\n", + (unsigned long long)eb->start, eb->len); + free_extent_buffer_nocache(eb); + } else { + free_extent_buffer_final(eb); + } + } + + free_extent_cache_tree(&fs_info->extent_cache); + fs_info->cache_size = 0; +} + void extent_io_tree_init(struct extent_io_tree *tree) { cache_tree_init(&tree->state); cache_tree_init(&tree->cache); INIT_LIST_HEAD(&tree->lru); - tree->cache_size = 0; - tree->max_cache_size = (u64)total_memory() / 4; } static struct extent_state *alloc_extent_state(void) @@ -74,7 +106,6 @@ static void free_extent_state_func(struct cache_extent *cache) btrfs_free_extent_state(es); } -static void free_extent_buffer_final(struct extent_buffer *eb); void extent_io_tree_cleanup(struct extent_io_tree *tree) { struct extent_buffer *eb; @@ -645,11 +676,9 @@ static void free_extent_buffer_final(struct extent_buffer *eb) BUG_ON(eb->refs); list_del_init(&eb->lru); if (!(eb->flags & EXTENT_BUFFER_DUMMY)) { - struct extent_io_tree *tree = &eb->fs_info->extent_cache; - - remove_cache_extent(&tree->cache, &eb->cache_node); - BUG_ON(tree->cache_size < eb->len); - tree->cache_size -= eb->len; + remove_cache_extent(&eb->fs_info->extent_cache, &eb->cache_node); + BUG_ON(eb->fs_info->cache_size < eb->len); + eb->fs_info->cache_size -= eb->len; } free(eb); } @@ -686,15 +715,14 @@ void free_extent_buffer_nocache(struct extent_buffer *eb) struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, u64 bytenr, u32 blocksize) { - struct extent_io_tree *tree = &fs_info->extent_cache; struct extent_buffer *eb = NULL; struct cache_extent *cache; - cache = lookup_cache_extent(&tree->cache, bytenr, blocksize); + cache = lookup_cache_extent(&fs_info->extent_cache, bytenr, blocksize); if (cache && cache->start == bytenr && cache->size == blocksize) { eb = container_of(cache, struct extent_buffer, cache_node); - list_move_tail(&eb->lru, &tree->lru); + list_move_tail(&eb->lru, &fs_info->lru); eb->refs++; } return eb; @@ -703,27 +731,26 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, struct extent_buffer *find_first_extent_buffer(struct btrfs_fs_info *fs_info, u64 start) { - struct extent_io_tree *tree = &fs_info->extent_cache; struct extent_buffer *eb = NULL; struct cache_extent *cache; - cache = search_cache_extent(&tree->cache, start); + cache = search_cache_extent(&fs_info->extent_cache, start); if (cache) { eb = container_of(cache, struct extent_buffer, cache_node); - list_move_tail(&eb->lru, &tree->lru); + list_move_tail(&eb->lru, &fs_info->lru); eb->refs++; } return eb; } -static void trim_extent_buffer_cache(struct extent_io_tree *tree) +static void trim_extent_buffer_cache(struct btrfs_fs_info *fs_info) { struct extent_buffer *eb, *tmp; - list_for_each_entry_safe(eb, tmp, &tree->lru, lru) { + list_for_each_entry_safe(eb, tmp, &fs_info->lru, lru) { if (eb->refs == 0) free_extent_buffer_final(eb); - if (tree->cache_size <= ((tree->max_cache_size * 9) / 10)) + if (fs_info->cache_size <= ((fs_info->max_cache_size * 9) / 10)) break; } } @@ -732,14 +759,13 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 bytenr, u32 blocksize) { struct extent_buffer *eb; - struct extent_io_tree *tree = &fs_info->extent_cache; struct cache_extent *cache; - cache = lookup_cache_extent(&tree->cache, bytenr, blocksize); + cache = lookup_cache_extent(&fs_info->extent_cache, bytenr, blocksize); if (cache && cache->start == bytenr && cache->size == blocksize) { eb = container_of(cache, struct extent_buffer, cache_node); - list_move_tail(&eb->lru, &tree->lru); + list_move_tail(&eb->lru, &fs_info->lru); eb->refs++; } else { int ret; @@ -752,15 +778,15 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, eb = __alloc_extent_buffer(fs_info, bytenr, blocksize); if (!eb) return NULL; - ret = insert_cache_extent(&tree->cache, &eb->cache_node); + ret = insert_cache_extent(&fs_info->extent_cache, &eb->cache_node); if (ret) { free(eb); return NULL; } - list_add_tail(&eb->lru, &tree->lru); - tree->cache_size += blocksize; - if (tree->cache_size >= tree->max_cache_size) - trim_extent_buffer_cache(tree); + list_add_tail(&eb->lru, &fs_info->lru); + fs_info->cache_size += blocksize; + if (fs_info->cache_size >= fs_info->max_cache_size) + trim_extent_buffer_cache(fs_info); } return eb; } diff --git a/kernel-shared/extent_io.h b/kernel-shared/extent_io.h index e4ae2dcd..1c7dbc51 100644 --- a/kernel-shared/extent_io.h +++ b/kernel-shared/extent_io.h @@ -165,5 +165,7 @@ void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start, unsigned long pos, unsigned long len); void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, unsigned long pos, unsigned long len); +void extent_buffer_init_cache(struct btrfs_fs_info *fs_info); +void extent_buffer_free_cache(struct btrfs_fs_info *fs_info); #endif