diff mbox

Btrfs-progs: fix memory leaks on cleanup

Message ID 1363619223-4242-1-git-send-email-jbacik@fusionio.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Josef Bacik March 18, 2013, 3:07 p.m. UTC
I've been working on btrfs-image and I kept seeing these leaks pop up on
valgrind so I'm just fixing them.  We don't properly cleanup the device cache,
the chunk tree mapping cache, or the space infos on close.  With this patch
valgrind doesn't complain about any memory leaks running btrfs-image.  Thanks,

Signed-off-by: Josef Bacik <jbacik@fusionio.com>
---
 disk-io.c     |   26 +++++++++++++++++++++-----
 extent-tree.c |    9 +++++++++
 2 files changed, 30 insertions(+), 5 deletions(-)
diff mbox

Patch

diff --git a/disk-io.c b/disk-io.c
index da7086f..72b33da 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -1269,23 +1269,38 @@  int write_ctree_super(struct btrfs_trans_handle *trans,
 static int close_all_devices(struct btrfs_fs_info *fs_info)
 {
 	struct list_head *list;
-	struct list_head *next;
 	struct btrfs_device *device;
 
-	return 0;
-
 	list = &fs_info->fs_devices->devices;
-	list_for_each(next, list) {
-		device = list_entry(next, struct btrfs_device, dev_list);
+	while (!list_empty(list)) {
+		device = list_entry(list->next, struct btrfs_device, dev_list);
+		list_del_init(&device->dev_list);
 		if (device->fd) {
 			fsync(device->fd);
 			posix_fadvise(device->fd, 0, 0, POSIX_FADV_DONTNEED);
 		}
 		close(device->fd);
+		kfree(device->name);
+		kfree(device->label);
+		kfree(device);
 	}
+	kfree(fs_info->fs_devices);
 	return 0;
 }
 
+static void free_mapping_cache(struct btrfs_fs_info *fs_info)
+{
+	struct cache_tree *cache_tree = &fs_info->mapping_tree.cache_tree;
+	struct cache_extent *ce;
+	struct map_lookup *map;
+
+	while ((ce = find_first_cache_extent(cache_tree, 0))) {
+		map = container_of(ce, struct map_lookup, ce);
+		remove_cache_extent(cache_tree, ce);
+		kfree(map);
+	}
+}
+
 int close_ctree(struct btrfs_root *root)
 {
 	int ret;
@@ -1326,6 +1341,7 @@  int close_ctree(struct btrfs_root *root)
 	}
 
 	close_all_devices(fs_info);
+	free_mapping_cache(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);
diff --git a/extent-tree.c b/extent-tree.c
index eede633..ba47688 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -3172,10 +3172,12 @@  out:
 
 int btrfs_free_block_groups(struct btrfs_fs_info *info)
 {
+	struct btrfs_space_info *sinfo;
 	u64 start;
 	u64 end;
 	u64 ptr;
 	int ret;
+
 	while(1) {
 		ret = find_first_extent_bit(&info->block_group_cache, 0,
 					    &start, &end, (unsigned int)-1);
@@ -3195,6 +3197,13 @@  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)) {
+		sinfo = list_entry(info->space_info.next,
+				   struct btrfs_space_info, list);
+		list_del_init(&sinfo->list);
+		kfree(sinfo);
+	}
 	return 0;
 }