aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-05-02 15:53:43 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-05-02 15:53:43 -0400
commit35b7e476107e3d54f03384e0f2fa3dfd68933353 (patch)
tree51a7e7cffad309b0aa0d3d054d7ecc5b8be72298 /fs/btrfs
parent090d18753c7fb73f7d846c3a89a50cd35136d144 (diff)
Btrfs: fix page cache memory leak
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/bit-radix.c2
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/dir-item.c11
-rw-r--r--fs/btrfs/disk-io.c8
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent-tree.c12
-rw-r--r--fs/btrfs/hash.c1
-rw-r--r--fs/btrfs/print-tree.c1
-rw-r--r--fs/btrfs/super.c56
-rw-r--r--fs/btrfs/transaction.c8
10 files changed, 59 insertions, 45 deletions
diff --git a/fs/btrfs/bit-radix.c b/fs/btrfs/bit-radix.c
index 9fc42e99c7df..e9ace32d7bae 100644
--- a/fs/btrfs/bit-radix.c
+++ b/fs/btrfs/bit-radix.c
@@ -22,9 +22,7 @@ int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
22 return -ENOMEM; 22 return -ENOMEM;
23 memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long)); 23 memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long));
24 bits[0] = slot; 24 bits[0] = slot;
25 radix_tree_preload(GFP_NOFS);
26 ret = radix_tree_insert(radix, slot, bits); 25 ret = radix_tree_insert(radix, slot, bits);
27 radix_tree_preload_end();
28 if (ret) 26 if (ret)
29 return ret; 27 return ret;
30 } 28 }
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index e6bf9919536a..b5855a5365ef 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -8,6 +8,9 @@
8 8
9struct btrfs_trans_handle; 9struct btrfs_trans_handle;
10struct btrfs_transaction; 10struct btrfs_transaction;
11extern struct kmem_cache *btrfs_trans_handle_cachep;
12extern struct kmem_cache *btrfs_transaction_cachep;
13extern struct kmem_cache *btrfs_bit_radix_cachep;
11extern struct kmem_cache *btrfs_path_cachep; 14extern struct kmem_cache *btrfs_path_cachep;
12 15
13#define BTRFS_MAGIC "_BtRfS_M" 16#define BTRFS_MAGIC "_BtRfS_M"
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index 7a7e9846860a..00a28d90fea6 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -4,11 +4,12 @@
4#include "hash.h" 4#include "hash.h"
5#include "transaction.h" 5#include "transaction.h"
6 6
7struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle *trans, 7static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
8 struct btrfs_root *root, 8 *trans,
9 struct btrfs_path *path, 9 struct btrfs_root *root,
10 struct btrfs_key *cpu_key, 10 struct btrfs_path *path,
11 u32 data_size) 11 struct btrfs_key *cpu_key,
12 u32 data_size)
12{ 13{
13 int ret; 14 int ret;
14 char *ptr; 15 char *ptr;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 354524adf984..5828a104dfef 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -5,7 +5,7 @@
5#include <linux/scatterlist.h> 5#include <linux/scatterlist.h>
6#include <linux/swap.h> 6#include <linux/swap.h>
7#include <linux/radix-tree.h> 7#include <linux/radix-tree.h>
8#include <linux/file.h> 8#include <linux/writeback.h>
9#include "ctree.h" 9#include "ctree.h"
10#include "disk-io.h" 10#include "disk-io.h"
11#include "transaction.h" 11#include "transaction.h"
@@ -694,7 +694,7 @@ static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
694 return 0; 694 return 0;
695} 695}
696 696
697int del_fs_roots(struct btrfs_fs_info *fs_info) 697static int del_fs_roots(struct btrfs_fs_info *fs_info)
698{ 698{
699 int ret; 699 int ret;
700 struct btrfs_root *gang[8]; 700 struct btrfs_root *gang[8];
@@ -781,3 +781,7 @@ void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf)
781 brelse(buf); 781 brelse(buf);
782} 782}
783 783
784void btrfs_btree_balance_dirty(struct btrfs_root *root)
785{
786 balance_dirty_pages_ratelimited(root->fs_info->btree_inode->i_mapping);
787}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 1ee7d2a55b5b..822ccb8aa4ae 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -55,4 +55,6 @@ int btrfs_insert_dev_radix(struct btrfs_root *root,
55 u64 num_blocks); 55 u64 num_blocks);
56int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, 56int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh,
57 u64 logical); 57 u64 logical);
58int btrfs_releasepage(struct page *page, gfp_t flags);
59void btrfs_btree_balance_dirty(struct btrfs_root *root);
58#endif 60#endif
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 2837fddf7b1c..0e20d1c42fca 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -322,18 +322,10 @@ static int update_block_group(struct btrfs_trans_handle *trans,
322 return 0; 322 return 0;
323} 323}
324 324
325static int try_remove_page(struct address_space *mapping, unsigned long index)
326{
327 int ret;
328 ret = invalidate_mapping_pages(mapping, index, index);
329 return ret;
330}
331
332int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct 325int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
333 btrfs_root *root) 326 btrfs_root *root)
334{ 327{
335 unsigned long gang[8]; 328 unsigned long gang[8];
336 struct inode *btree_inode = root->fs_info->btree_inode;
337 u64 first = 0; 329 u64 first = 0;
338 int ret; 330 int ret;
339 int i; 331 int i;
@@ -348,9 +340,6 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
348 first = gang[0]; 340 first = gang[0];
349 for (i = 0; i < ret; i++) { 341 for (i = 0; i < ret; i++) {
350 clear_radix_bit(pinned_radix, gang[i]); 342 clear_radix_bit(pinned_radix, gang[i]);
351 try_remove_page(btree_inode->i_mapping,
352 gang[i] << (PAGE_CACHE_SHIFT -
353 btree_inode->i_blkbits));
354 } 343 }
355 } 344 }
356 return 0; 345 return 0;
@@ -983,6 +972,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
983 break; 972 break;
984 if (wret < 0) 973 if (wret < 0)
985 ret = wret; 974 ret = wret;
975 btrfs_btree_balance_dirty(root);
986 } 976 }
987 for (i = 0; i <= orig_level; i++) { 977 for (i = 0; i <= orig_level; i++) {
988 if (path->nodes[i]) { 978 if (path->nodes[i]) {
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c
index 22519b8e0cf2..32de1ea1b64e 100644
--- a/fs/btrfs/hash.c
+++ b/fs/btrfs/hash.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include "hash.h"
14#define DELTA 0x9E3779B9 15#define DELTA 0x9E3779B9
15 16
16static void TEA_transform(__u32 buf[2], __u32 const in[]) 17static void TEA_transform(__u32 buf[2], __u32 const in[])
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c
index 2f95fc67a036..28813411de66 100644
--- a/fs/btrfs/print-tree.c
+++ b/fs/btrfs/print-tree.c
@@ -1,6 +1,7 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include "ctree.h" 2#include "ctree.h"
3#include "disk-io.h" 3#include "disk-io.h"
4#include "print-tree.h"
4 5
5void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) 6void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
6{ 7{
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index a29a781b86c2..130a1d3d9f5f 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -18,14 +18,14 @@
18#include "btrfs_inode.h" 18#include "btrfs_inode.h"
19#include "ioctl.h" 19#include "ioctl.h"
20 20
21void btrfs_fsinfo_release(struct kobject *obj) 21static void btrfs_fsinfo_release(struct kobject *obj)
22{ 22{
23 struct btrfs_fs_info *fsinfo = container_of(obj, 23 struct btrfs_fs_info *fsinfo = container_of(obj,
24 struct btrfs_fs_info, kobj); 24 struct btrfs_fs_info, kobj);
25 kfree(fsinfo); 25 kfree(fsinfo);
26} 26}
27 27
28struct kobj_type btrfs_fsinfo_ktype = { 28static struct kobj_type btrfs_fsinfo_ktype = {
29 .release = btrfs_fsinfo_release, 29 .release = btrfs_fsinfo_release,
30}; 30};
31 31
@@ -148,7 +148,6 @@ static void fill_inode_item(struct btrfs_inode_item *item,
148 BTRFS_I(inode)->block_group->key.objectid); 148 BTRFS_I(inode)->block_group->key.objectid);
149} 149}
150 150
151
152static int btrfs_update_inode(struct btrfs_trans_handle *trans, 151static int btrfs_update_inode(struct btrfs_trans_handle *trans,
153 struct btrfs_root *root, 152 struct btrfs_root *root,
154 struct inode *inode) 153 struct inode *inode)
@@ -251,6 +250,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
251 ret = btrfs_unlink_trans(trans, root, dir, dentry); 250 ret = btrfs_unlink_trans(trans, root, dir, dentry);
252 btrfs_end_transaction(trans, root); 251 btrfs_end_transaction(trans, root);
253 mutex_unlock(&root->fs_info->fs_mutex); 252 mutex_unlock(&root->fs_info->fs_mutex);
253 btrfs_btree_balance_dirty(root);
254 return ret; 254 return ret;
255} 255}
256 256
@@ -324,6 +324,7 @@ out:
324 btrfs_free_path(path); 324 btrfs_free_path(path);
325 mutex_unlock(&root->fs_info->fs_mutex); 325 mutex_unlock(&root->fs_info->fs_mutex);
326 ret = btrfs_end_transaction(trans, root); 326 ret = btrfs_end_transaction(trans, root);
327 btrfs_btree_balance_dirty(root);
327 if (ret && !err) 328 if (ret && !err)
328 err = ret; 329 err = ret;
329 return err; 330 return err;
@@ -449,6 +450,7 @@ static void btrfs_delete_inode(struct inode *inode)
449 btrfs_free_inode(trans, root, inode); 450 btrfs_free_inode(trans, root, inode);
450 btrfs_end_transaction(trans, root); 451 btrfs_end_transaction(trans, root);
451 mutex_unlock(&root->fs_info->fs_mutex); 452 mutex_unlock(&root->fs_info->fs_mutex);
453 btrfs_btree_balance_dirty(root);
452 return; 454 return;
453no_delete: 455no_delete:
454 clear_inode(inode); 456 clear_inode(inode);
@@ -481,7 +483,7 @@ out:
481 return ret; 483 return ret;
482} 484}
483 485
484int fixup_tree_root_location(struct btrfs_root *root, 486static int fixup_tree_root_location(struct btrfs_root *root,
485 struct btrfs_key *location, 487 struct btrfs_key *location,
486 struct btrfs_root **sub_root) 488 struct btrfs_root **sub_root)
487{ 489{
@@ -512,7 +514,7 @@ int fixup_tree_root_location(struct btrfs_root *root,
512 return 0; 514 return 0;
513} 515}
514 516
515int btrfs_init_locked_inode(struct inode *inode, void *p) 517static int btrfs_init_locked_inode(struct inode *inode, void *p)
516{ 518{
517 struct btrfs_iget_args *args = p; 519 struct btrfs_iget_args *args = p;
518 inode->i_ino = args->ino; 520 inode->i_ino = args->ino;
@@ -520,15 +522,15 @@ int btrfs_init_locked_inode(struct inode *inode, void *p)
520 return 0; 522 return 0;
521} 523}
522 524
523int btrfs_find_actor(struct inode *inode, void *opaque) 525static int btrfs_find_actor(struct inode *inode, void *opaque)
524{ 526{
525 struct btrfs_iget_args *args = opaque; 527 struct btrfs_iget_args *args = opaque;
526 return (args->ino == inode->i_ino && 528 return (args->ino == inode->i_ino &&
527 args->root == BTRFS_I(inode)->root); 529 args->root == BTRFS_I(inode)->root);
528} 530}
529 531
530struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid, 532static struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid,
531 struct btrfs_root *root) 533 struct btrfs_root *root)
532{ 534{
533 struct inode *inode; 535 struct inode *inode;
534 struct btrfs_iget_args args; 536 struct btrfs_iget_args args;
@@ -790,6 +792,7 @@ static void btrfs_dirty_inode(struct inode *inode)
790 btrfs_update_inode(trans, root, inode); 792 btrfs_update_inode(trans, root, inode);
791 btrfs_end_transaction(trans, root); 793 btrfs_end_transaction(trans, root);
792 mutex_unlock(&root->fs_info->fs_mutex); 794 mutex_unlock(&root->fs_info->fs_mutex);
795 btrfs_btree_balance_dirty(root);
793} 796}
794 797
795static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, 798static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
@@ -913,6 +916,7 @@ out_unlock:
913 inode_dec_link_count(inode); 916 inode_dec_link_count(inode);
914 iput(inode); 917 iput(inode);
915 } 918 }
919 btrfs_btree_balance_dirty(root);
916 return err; 920 return err;
917} 921}
918 922
@@ -1002,6 +1006,7 @@ out_unlock:
1002 mutex_unlock(&root->fs_info->fs_mutex); 1006 mutex_unlock(&root->fs_info->fs_mutex);
1003 if (drop_on_err) 1007 if (drop_on_err)
1004 iput(inode); 1008 iput(inode);
1009 btrfs_btree_balance_dirty(root);
1005 return err; 1010 return err;
1006} 1011}
1007 1012
@@ -1099,7 +1104,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
1099 found_type != BTRFS_EXTENT_DATA_KEY) { 1104 found_type != BTRFS_EXTENT_DATA_KEY) {
1100 extent_end = 0; 1105 extent_end = 0;
1101 extent_start = 0; 1106 extent_start = 0;
1102 btrfs_release_path(root, path);
1103 goto out; 1107 goto out;
1104 } 1108 }
1105 found_type = btrfs_file_extent_type(item); 1109 found_type = btrfs_file_extent_type(item);
@@ -1135,7 +1139,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
1135 btrfs_map_bh_to_logical(root, result, 0); 1139 btrfs_map_bh_to_logical(root, result, 0);
1136 } 1140 }
1137out: 1141out:
1138 btrfs_release_path(root, path);
1139 btrfs_free_path(path); 1142 btrfs_free_path(path);
1140 return err; 1143 return err;
1141} 1144}
@@ -1231,13 +1234,13 @@ static int __btrfs_write_full_page(struct inode *inode, struct page *page,
1231 } else if (!buffer_mapped(bh) && buffer_dirty(bh)) { 1234 } else if (!buffer_mapped(bh) && buffer_dirty(bh)) {
1232 WARN_ON(bh->b_size != blocksize); 1235 WARN_ON(bh->b_size != blocksize);
1233 err = btrfs_get_block(inode, block, bh, 0); 1236 err = btrfs_get_block(inode, block, bh, 0);
1234 if (err) 1237 if (err) {
1238printk("writepage going to recovery err %d\n", err);
1235 goto recover; 1239 goto recover;
1240 }
1236 if (buffer_new(bh)) { 1241 if (buffer_new(bh)) {
1237 /* blockdev mappings never come here */ 1242 /* blockdev mappings never come here */
1238 clear_buffer_new(bh); 1243 clear_buffer_new(bh);
1239 unmap_underlying_metadata(bh->b_bdev,
1240 bh->b_blocknr);
1241 } 1244 }
1242 } 1245 }
1243 bh = bh->b_this_page; 1246 bh = bh->b_this_page;
@@ -1303,11 +1306,6 @@ done:
1303 if (uptodate) 1306 if (uptodate)
1304 SetPageUptodate(page); 1307 SetPageUptodate(page);
1305 end_page_writeback(page); 1308 end_page_writeback(page);
1306 /*
1307 * The page and buffer_heads can be released at any time from
1308 * here on.
1309 */
1310 wbc->pages_skipped++; /* We didn't write this page */
1311 } 1309 }
1312 return err; 1310 return err;
1313 1311
@@ -1409,10 +1407,11 @@ static void btrfs_truncate(struct inode *inode)
1409 btrfs_set_trans_block_group(trans, inode); 1407 btrfs_set_trans_block_group(trans, inode);
1410 ret = btrfs_truncate_in_trans(trans, root, inode); 1408 ret = btrfs_truncate_in_trans(trans, root, inode);
1411 BUG_ON(ret); 1409 BUG_ON(ret);
1410 btrfs_update_inode(trans, root, inode);
1412 ret = btrfs_end_transaction(trans, root); 1411 ret = btrfs_end_transaction(trans, root);
1413 BUG_ON(ret); 1412 BUG_ON(ret);
1414 mutex_unlock(&root->fs_info->fs_mutex); 1413 mutex_unlock(&root->fs_info->fs_mutex);
1415 mark_inode_dirty(inode); 1414 btrfs_btree_balance_dirty(root);
1416} 1415}
1417 1416
1418/* 1417/*
@@ -1777,10 +1776,15 @@ static int prepare_pages(struct btrfs_root *root,
1777 err = -ENOMEM; 1776 err = -ENOMEM;
1778 goto failed_release; 1777 goto failed_release;
1779 } 1778 }
1779 cancel_dirty_page(pages[i], PAGE_CACHE_SIZE);
1780 wait_on_page_writeback(pages[i]);
1780 offset = pos & (PAGE_CACHE_SIZE -1); 1781 offset = pos & (PAGE_CACHE_SIZE -1);
1781 this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); 1782 this_write = min(PAGE_CACHE_SIZE - offset, write_bytes);
1782 create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, 1783 if (!page_has_buffers(pages[i])) {
1783 (1 << BH_Uptodate)); 1784 create_empty_buffers(pages[i],
1785 root->fs_info->sb->s_blocksize,
1786 (1 << BH_Uptodate));
1787 }
1784 head = page_buffers(pages[i]); 1788 head = page_buffers(pages[i]);
1785 bh = head; 1789 bh = head;
1786 do { 1790 do {
@@ -1820,7 +1824,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1820 struct inode *inode = file->f_path.dentry->d_inode; 1824 struct inode *inode = file->f_path.dentry->d_inode;
1821 struct btrfs_root *root = BTRFS_I(inode)->root; 1825 struct btrfs_root *root = BTRFS_I(inode)->root;
1822 struct page *pages[8]; 1826 struct page *pages[8];
1823 struct page *pinned[2] = { NULL, NULL }; 1827 struct page *pinned[2];
1824 unsigned long first_index; 1828 unsigned long first_index;
1825 unsigned long last_index; 1829 unsigned long last_index;
1826 u64 start_pos; 1830 u64 start_pos;
@@ -1829,6 +1833,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1829 struct btrfs_trans_handle *trans; 1833 struct btrfs_trans_handle *trans;
1830 struct btrfs_key ins; 1834 struct btrfs_key ins;
1831 1835
1836 pinned[0] = NULL;
1837 pinned[1] = NULL;
1832 if (file->f_flags & O_DIRECT) 1838 if (file->f_flags & O_DIRECT)
1833 return -EINVAL; 1839 return -EINVAL;
1834 pos = *ppos; 1840 pos = *ppos;
@@ -1858,6 +1864,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1858 if (!PageUptodate(pinned[0])) { 1864 if (!PageUptodate(pinned[0])) {
1859 ret = mpage_readpage(pinned[0], btrfs_get_block); 1865 ret = mpage_readpage(pinned[0], btrfs_get_block);
1860 BUG_ON(ret); 1866 BUG_ON(ret);
1867 wait_on_page_locked(pinned[0]);
1861 } else { 1868 } else {
1862 unlock_page(pinned[0]); 1869 unlock_page(pinned[0]);
1863 } 1870 }
@@ -1869,6 +1876,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1869 if (!PageUptodate(pinned[1])) { 1876 if (!PageUptodate(pinned[1])) {
1870 ret = mpage_readpage(pinned[1], btrfs_get_block); 1877 ret = mpage_readpage(pinned[1], btrfs_get_block);
1871 BUG_ON(ret); 1878 BUG_ON(ret);
1879 wait_on_page_locked(pinned[1]);
1872 } else { 1880 } else {
1873 unlock_page(pinned[1]); 1881 unlock_page(pinned[1]);
1874 } 1882 }
@@ -1940,6 +1948,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1940 num_written += write_bytes; 1948 num_written += write_bytes;
1941 1949
1942 balance_dirty_pages_ratelimited(inode->i_mapping); 1950 balance_dirty_pages_ratelimited(inode->i_mapping);
1951 btrfs_btree_balance_dirty(root);
1943 cond_resched(); 1952 cond_resched();
1944 } 1953 }
1945out_unlock: 1954out_unlock:
@@ -2165,6 +2174,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
2165 iput(inode); 2174 iput(inode);
2166 2175
2167 mutex_unlock(&root->fs_info->fs_mutex); 2176 mutex_unlock(&root->fs_info->fs_mutex);
2177 btrfs_btree_balance_dirty(root);
2168 return 0; 2178 return 0;
2169} 2179}
2170 2180
@@ -2220,6 +2230,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
2220 ret = btrfs_commit_transaction(trans, root); 2230 ret = btrfs_commit_transaction(trans, root);
2221 BUG_ON(ret); 2231 BUG_ON(ret);
2222 mutex_unlock(&root->fs_info->fs_mutex); 2232 mutex_unlock(&root->fs_info->fs_mutex);
2233 btrfs_btree_balance_dirty(root);
2223 return 0; 2234 return 0;
2224} 2235}
2225 2236
@@ -2295,6 +2306,7 @@ out:
2295 mutex_unlock(&root->fs_info->fs_mutex); 2306 mutex_unlock(&root->fs_info->fs_mutex);
2296out_nolock: 2307out_nolock:
2297 btrfs_free_path(path); 2308 btrfs_free_path(path);
2309 btrfs_btree_balance_dirty(root);
2298 2310
2299 return ret; 2311 return ret;
2300} 2312}
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index bdbf514c111f..8bbe9107ff7e 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -199,8 +199,9 @@ struct dirty_root {
199 struct btrfs_root *root; 199 struct btrfs_root *root;
200}; 200};
201 201
202int add_dirty_roots(struct btrfs_trans_handle *trans, 202static int add_dirty_roots(struct btrfs_trans_handle *trans,
203 struct radix_tree_root *radix, struct list_head *list) 203 struct radix_tree_root *radix,
204 struct list_head *list)
204{ 205{
205 struct dirty_root *dirty; 206 struct dirty_root *dirty;
206 struct btrfs_root *gang[8]; 207 struct btrfs_root *gang[8];
@@ -246,7 +247,8 @@ int add_dirty_roots(struct btrfs_trans_handle *trans,
246 return 0; 247 return 0;
247} 248}
248 249
249int drop_dirty_roots(struct btrfs_root *tree_root, struct list_head *list) 250static int drop_dirty_roots(struct btrfs_root *tree_root,
251 struct list_head *list)
250{ 252{
251 struct dirty_root *dirty; 253 struct dirty_root *dirty;
252 struct btrfs_trans_handle *trans; 254 struct btrfs_trans_handle *trans;