Blob Blame History Raw
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 <jbacik@redhat.com>
---
 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