diff --git a/btrfs-progs-valgrind.patch b/btrfs-progs-valgrind.patch new file mode 100644 index 0000000..3adbe57 --- /dev/null +++ b/btrfs-progs-valgrind.patch @@ -0,0 +1,247 @@ +Hello, + +Started running valgrind against btrfsck since e2fsck seemed to have a myriad of +problems. btrfsck was actually not in too bad shape, only like 5 or 6 normal +errors and maybe 5 leaks. The big leak is the "seen" extent cache that we don't +seem to do anything with. Since I'm not sure what Yan is up to I just made it +so we free that cache before we return in case he wants it for something. With +these changes btrfsck doesn't spit out any errors while running valgrind and has +no leaks. This should also help any of the other utilities that use the generic +stuff. Thanks, + +Signed-off-by: Josef Bacik +--- + btrfsck.c | 2 ++ + disk-io.c | 29 ++++++++++++++++++----------- + extent-cache.c | 11 +++++++++++ + extent-cache.h | 1 + + extent-tree.c | 10 ++++++++++ + extent_io.c | 1 + + volumes.c | 16 +++++++++++++++- + volumes.h | 1 + + 8 files changed, 59 insertions(+), 12 deletions(-) + +diff --git a/btrfsck.c b/btrfsck.c +index 40c90f8..9dd777f 100644 +--- a/btrfsck.c ++++ b/btrfsck.c +@@ -2431,6 +2431,8 @@ static int check_extents(struct btrfs_root *root) + break; + } + ret = check_extent_refs(root, &extent_cache); ++ free_cache_tree(&seen); ++ free(bits); + return ret; + } + +diff --git a/disk-io.c b/disk-io.c +index addebe1..4d4e902 100644 +--- a/disk-io.c ++++ b/disk-io.c +@@ -425,8 +425,10 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root, + u64 blocknr = btrfs_super_log_root(disk_super); + struct btrfs_root *log_root = malloc(sizeof(struct btrfs_root)); + +- if (blocknr == 0) ++ if (blocknr == 0) { ++ free(log_root); + return 0; ++ } + + blocksize = btrfs_level_size(tree_root, + btrfs_super_log_root_level(disk_super)); +@@ -605,7 +607,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, + struct btrfs_root *chunk_root = malloc(sizeof(struct btrfs_root)); + struct btrfs_root *dev_root = malloc(sizeof(struct btrfs_root)); + struct btrfs_root *csum_root = malloc(sizeof(struct btrfs_root)); +- struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); ++ struct btrfs_fs_info *fs_info = malloc(sizeof(struct btrfs_fs_info)); + int ret; + struct btrfs_super_block *disk_super; + struct btrfs_fs_devices *fs_devices = NULL; +@@ -628,7 +630,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, + BUG_ON(ret); + } + +- memset(fs_info, 0, sizeof(*fs_info)); ++ memset(fs_info, 0, sizeof(struct btrfs_fs_info)); + fs_info->tree_root = tree_root; + fs_info->extent_root = extent_root; + fs_info->chunk_root = chunk_root; +@@ -928,15 +930,19 @@ static int close_all_devices(struct btrfs_fs_info *fs_info) + { + struct list_head *list; + struct list_head *next; ++ struct list_head *tmp; + struct btrfs_device *device; + +- return 0; +- + list = &fs_info->fs_devices->devices; +- list_for_each(next, list) { ++ list_for_each_safe(next, tmp, list) { + device = list_entry(next, struct btrfs_device, dev_list); + close(device->fd); ++ list_del(&device->dev_list); ++ free(device->name); ++ free(device->label); ++ free(device); + } ++ free(fs_info->fs_devices); + return 0; + } + +@@ -970,25 +976,26 @@ int close_ctree(struct btrfs_root *root) + if (fs_info->csum_root->node) + free_extent_buffer(fs_info->csum_root->node); + +- if (root->fs_info->log_root_tree) { +- if (root->fs_info->log_root_tree->node) +- free_extent_buffer(root->fs_info->log_root_tree->node); +- free(root->fs_info->log_root_tree); ++ if (fs_info->log_root_tree) { ++ if (fs_info->log_root_tree->node) ++ free_extent_buffer(fs_info->log_root_tree->node); + } + +- close_all_devices(root->fs_info); ++ close_all_devices(fs_info); + extent_io_tree_cleanup(&fs_info->extent_cache); + extent_io_tree_cleanup(&fs_info->free_space_cache); + extent_io_tree_cleanup(&fs_info->block_group_cache); + extent_io_tree_cleanup(&fs_info->pinned_extents); + extent_io_tree_cleanup(&fs_info->pending_del); + extent_io_tree_cleanup(&fs_info->extent_ins); ++ btrfs_mapping_tree_free(&fs_info->mapping_tree); + + free(fs_info->tree_root); + free(fs_info->extent_root); + free(fs_info->chunk_root); + free(fs_info->dev_root); + free(fs_info->csum_root); ++ free(fs_info->log_root_tree); + free(fs_info); + + return 0; +diff --git a/extent-cache.c b/extent-cache.c +index b871e18..b424975 100644 +--- a/extent-cache.c ++++ b/extent-cache.c +@@ -170,3 +170,14 @@ void remove_cache_extent(struct cache_tree *tree, + rb_erase(&pe->rb_node, &tree->root); + } + ++void free_cache_tree(struct cache_tree *tree) ++{ ++ struct rb_node *node; ++ struct cache_extent *cache; ++ ++ while ((node = rb_last(&tree->root)) != NULL) { ++ cache = rb_entry(node, struct cache_extent, rb_node); ++ remove_cache_extent(tree, cache); ++ free(cache); ++ } ++} +diff --git a/extent-cache.h b/extent-cache.h +index 7f2f2a6..1696bc2 100644 +--- a/extent-cache.h ++++ b/extent-cache.h +@@ -43,6 +43,7 @@ struct cache_extent *find_cache_extent(struct cache_tree *tree, + int insert_cache_extent(struct cache_tree *tree, u64 start, u64 size); + int insert_existing_cache_extent(struct cache_tree *tree, + struct cache_extent *pe); ++void free_cache_tree(struct cache_tree *tree); + + static inline int cache_tree_empty(struct cache_tree *tree) + { +diff --git a/extent-tree.c b/extent-tree.c +index b2f9bb2..e1d7ffd 100644 +--- a/extent-tree.c ++++ b/extent-tree.c +@@ -2985,6 +2985,7 @@ out: + + int btrfs_free_block_groups(struct btrfs_fs_info *info) + { ++ struct btrfs_space_info *space_info; + u64 start; + u64 end; + u64 ptr; +@@ -3008,6 +3009,15 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) + clear_extent_dirty(&info->free_space_cache, start, + end, GFP_NOFS); + } ++ ++ while (!list_empty(&info->space_info)) { ++ space_info = list_entry(info->space_info.next, ++ struct btrfs_space_info, ++ list); ++ list_del(&space_info->list); ++ kfree(space_info); ++ } ++ + return 0; + } + +diff --git a/extent_io.c b/extent_io.c +index 069c199..71e6826 100644 +--- a/extent_io.c ++++ b/extent_io.c +@@ -572,6 +572,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, + BUG(); + return NULL; + } ++ memset(eb, 0, sizeof(struct extent_buffer) + blocksize); + + eb->start = bytenr; + eb->len = blocksize; +diff --git a/volumes.c b/volumes.c +index 7671855..eee66a7 100644 +--- a/volumes.c ++++ b/volumes.c +@@ -862,6 +862,20 @@ void btrfs_mapping_init(struct btrfs_mapping_tree *tree) + cache_tree_init(&tree->cache_tree); + } + ++void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree) ++{ ++ struct cache_extent *cache; ++ struct rb_node *node; ++ struct map_lookup *map; ++ ++ while ((node = rb_last(&tree->cache_tree.root)) != NULL) { ++ cache = rb_entry(node, struct cache_extent, rb_node); ++ map = container_of(cache, struct map_lookup, ce); ++ remove_cache_extent(&tree->cache_tree, cache); ++ free(map); ++ } ++} ++ + int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len) + { + struct cache_extent *ce; +@@ -1340,7 +1354,7 @@ int btrfs_read_sys_array(struct btrfs_root *root) + if (!sb) + return -ENOMEM; + btrfs_set_buffer_uptodate(sb); +- write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE); ++ write_extent_buffer(sb, super_copy, 0, sizeof(*super_copy)); + array_size = btrfs_super_sys_array_size(super_copy); + + /* +diff --git a/volumes.h b/volumes.h +index bb78751..e466b31 100644 +--- a/volumes.h ++++ b/volumes.h +@@ -130,4 +130,5 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans, + struct btrfs_root *root, struct btrfs_key *key, + struct btrfs_chunk *chunk, int item_size); + int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); ++void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree); + #endif +-- +1.5.4.3 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/btrfs-progs.spec b/btrfs-progs.spec index 7122fed..381cd25 100644 --- a/btrfs-progs.spec +++ b/btrfs-progs.spec @@ -1,6 +1,6 @@ Name: btrfs-progs Version: 0.19 -Release: 6%{?dist} +Release: 7%{?dist} Summary: Userspace programs for btrfs Group: System Environment/Base @@ -9,6 +9,7 @@ URL: http://btrfs.wiki.kernel.org/index.php/Main_Page Source0: http://www.kernel.org/pub/linux/kernel/people/mason/btrfs/%{name}-%{version}.tar.bz2 Patch0: btrfs-progs-fix-labels.patch Patch1: btrfs-progs-build-everything.patch +Patch2: btrfs-progs-valgrind.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: e2fsprogs-devel, libuuid-devel, zlib-devel, libacl-devel @@ -23,6 +24,7 @@ check, modify and correct any inconsistencies in the btrfs filesystem. %setup -q %patch0 -p1 %patch1 -p1 +%patch2 -p1 %build make CFLAGS="$RPM_OPT_FLAGS" %{?_smp_mflags} @@ -54,6 +56,9 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man8/mkfs.btrfs.8.gz %changelog +* Tue Aug 25 2009 Josef Bacik 0.19-7 +- add btrfs-progs-valgrind.patch to fix memory leaks and segfaults + * Fri Jul 24 2009 Fedora Release Engineering - 0.19-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild