aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2014-10-06 17:14:24 -0400
committerChris Mason <clm@fb.com>2014-11-20 20:14:26 -0500
commit40ae837b43565c47ee171e704d05947fd5c2bae9 (patch)
tree520debe05ef897cfd6a1031ff16033d82c9eb8e2 /fs
parentfce2a4e6b2da1bcc03837aff53b5bcb02bee4cee (diff)
Btrfs: don't leak pages and memory on compressed write error
In inode.c:submit_compressed_extents(), if we fail before calling btrfs_submit_compressed_write(), or when that function fails, we were freeing the async_extent structure without releasing its pages and freeing the pages array. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index ec68eaef05d7..b759585fbc6a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -633,6 +633,22 @@ free_pages_out:
633 goto out; 633 goto out;
634} 634}
635 635
636static void free_async_extent_pages(struct async_extent *async_extent)
637{
638 int i;
639
640 if (!async_extent->pages)
641 return;
642
643 for (i = 0; i < async_extent->nr_pages; i++) {
644 WARN_ON(async_extent->pages[i]->mapping);
645 page_cache_release(async_extent->pages[i]);
646 }
647 kfree(async_extent->pages);
648 async_extent->nr_pages = 0;
649 async_extent->pages = NULL;
650}
651
636/* 652/*
637 * phase two of compressed writeback. This is the ordered portion 653 * phase two of compressed writeback. This is the ordered portion
638 * of the code, which only gets called in the order the work was 654 * of the code, which only gets called in the order the work was
@@ -709,15 +725,7 @@ retry:
709 async_extent->compressed_size, 725 async_extent->compressed_size,
710 0, alloc_hint, &ins, 1, 1); 726 0, alloc_hint, &ins, 1, 1);
711 if (ret) { 727 if (ret) {
712 int i; 728 free_async_extent_pages(async_extent);
713
714 for (i = 0; i < async_extent->nr_pages; i++) {
715 WARN_ON(async_extent->pages[i]->mapping);
716 page_cache_release(async_extent->pages[i]);
717 }
718 kfree(async_extent->pages);
719 async_extent->nr_pages = 0;
720 async_extent->pages = NULL;
721 729
722 if (ret == -ENOSPC) { 730 if (ret == -ENOSPC) {
723 unlock_extent(io_tree, async_extent->start, 731 unlock_extent(io_tree, async_extent->start,
@@ -827,6 +835,7 @@ retry:
827 extent_clear_unlock_delalloc(inode, start, end, NULL, 0, 835 extent_clear_unlock_delalloc(inode, start, end, NULL, 0,
828 PAGE_END_WRITEBACK | 836 PAGE_END_WRITEBACK |
829 PAGE_SET_ERROR); 837 PAGE_SET_ERROR);
838 free_async_extent_pages(async_extent);
830 } 839 }
831 alloc_hint = ins.objectid + ins.offset; 840 alloc_hint = ins.objectid + ins.offset;
832 kfree(async_extent); 841 kfree(async_extent);
@@ -848,6 +857,7 @@ out_free:
848 PAGE_UNLOCK | PAGE_CLEAR_DIRTY | 857 PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
849 PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK | 858 PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK |
850 PAGE_SET_ERROR); 859 PAGE_SET_ERROR);
860 free_async_extent_pages(async_extent);
851 kfree(async_extent); 861 kfree(async_extent);
852 goto again; 862 goto again;
853} 863}