NFSv4: Eliminate nfs4_path_walk()
[safe/jmp/linux-2.6] / fs / btrfs / relocation.c
index 975fdd3..e558dd9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
 #include <linux/rbtree.h>
+#include <linux/slab.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
@@ -170,14 +171,14 @@ struct async_merge {
 
 static void mapping_tree_init(struct mapping_tree *tree)
 {
-       tree->rb_root.rb_node = NULL;
+       tree->rb_root = RB_ROOT;
        spin_lock_init(&tree->lock);
 }
 
 static void backref_cache_init(struct backref_cache *cache)
 {
        int i;
-       cache->rb_root.rb_node = NULL;
+       cache->rb_root = RB_ROOT;
        for (i = 0; i < BTRFS_MAX_LEVEL; i++)
                INIT_LIST_HEAD(&cache->pending[i]);
        spin_lock_init(&cache->lock);
@@ -1561,6 +1562,20 @@ static int invalidate_extent_cache(struct btrfs_root *root,
        return 0;
 }
 
+static void put_inodes(struct list_head *list)
+{
+       struct inodevec *ivec;
+       while (!list_empty(list)) {
+               ivec = list_entry(list->next, struct inodevec, list);
+               list_del(&ivec->list);
+               while (ivec->nr > 0) {
+                       ivec->nr--;
+                       iput(ivec->inode[ivec->nr]);
+               }
+               kfree(ivec);
+       }
+}
+
 static int find_next_key(struct btrfs_path *path, int level,
                         struct btrfs_key *key)
 
@@ -1723,6 +1738,11 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
 
                btrfs_btree_balance_dirty(root, nr);
 
+               /*
+                * put inodes outside transaction, otherwise we may deadlock.
+                */
+               put_inodes(&inode_list);
+
                if (replaced && rc->stage == UPDATE_DATA_PTRS)
                        invalidate_extent_cache(root, &key, &next_key);
        }
@@ -1752,19 +1772,7 @@ out:
 
        btrfs_btree_balance_dirty(root, nr);
 
-       /*
-        * put inodes while we aren't holding the tree locks
-        */
-       while (!list_empty(&inode_list)) {
-               struct inodevec *ivec;
-               ivec = list_entry(inode_list.next, struct inodevec, list);
-               list_del(&ivec->list);
-               while (ivec->nr > 0) {
-                       ivec->nr--;
-                       iput(ivec->inode[ivec->nr]);
-               }
-               kfree(ivec);
-       }
+       put_inodes(&inode_list);
 
        if (replaced && rc->stage == UPDATE_DATA_PTRS)
                invalidate_extent_cache(root, &key, &next_key);
@@ -2652,7 +2660,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                                        EXTENT_BOUNDARY, GFP_NOFS);
                        nr++;
                }
-               btrfs_set_extent_delalloc(inode, page_start, page_end);
+               btrfs_set_extent_delalloc(inode, page_start, page_end, NULL);
 
                set_page_dirty(page);
                dirty_page++;
@@ -3274,8 +3282,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
                return -ENOMEM;
 
        path = btrfs_alloc_path();
-       if (!path)
+       if (!path) {
+               kfree(cluster);
                return -ENOMEM;
+       }
 
        rc->extents_found = 0;
        rc->extents_skipped = 0;
@@ -3478,7 +3488,7 @@ static struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info,
        key.objectid = objectid;
        key.type = BTRFS_INODE_ITEM_KEY;
        key.offset = 0;
-       inode = btrfs_iget(root->fs_info->sb, &key, root);
+       inode = btrfs_iget(root->fs_info->sb, &key, root, NULL);
        BUG_ON(IS_ERR(inode) || is_bad_inode(inode));
        BTRFS_I(inode)->index_cnt = group->key.objectid;
 
@@ -3534,8 +3544,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
               (unsigned long long)rc->block_group->key.objectid,
               (unsigned long long)rc->block_group->flags);
 
-       btrfs_start_delalloc_inodes(fs_info->tree_root);
-       btrfs_wait_ordered_extents(fs_info->tree_root, 0);
+       btrfs_start_delalloc_inodes(fs_info->tree_root, 0);
+       btrfs_wait_ordered_extents(fs_info->tree_root, 0, 0);
 
        while (1) {
                rc->extents_found = 0;
@@ -3755,7 +3765,8 @@ out:
                                       BTRFS_DATA_RELOC_TREE_OBJECTID);
                if (IS_ERR(fs_root))
                        err = PTR_ERR(fs_root);
-               btrfs_orphan_cleanup(fs_root);
+               else
+                       btrfs_orphan_cleanup(fs_root);
        }
        return err;
 }