Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[safe/jmp/linux-2.6] / fs / btrfs / disk-io.c
index d4132aa..feca041 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include <linux/crc32c.h>
+#include <linux/slab.h>
 #include "compat.h"
 #include "ctree.h"
 #include "disk-io.h"
@@ -43,8 +44,6 @@ static struct extent_io_ops btree_extent_io_ops;
 static void end_workqueue_fn(struct btrfs_work *work);
 static void free_fs_root(struct btrfs_root *root);
 
-static atomic_t btrfs_bdi_num = ATOMIC_INIT(0);
-
 /*
  * end_io_wq structs are used to do processing in task context when an IO is
  * complete.  This is used during reads to verify checksums, and it is used
@@ -263,13 +262,15 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
 static int verify_parent_transid(struct extent_io_tree *io_tree,
                                 struct extent_buffer *eb, u64 parent_transid)
 {
+       struct extent_state *cached_state = NULL;
        int ret;
 
        if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
                return 0;
 
-       lock_extent(io_tree, eb->start, eb->start + eb->len - 1, GFP_NOFS);
-       if (extent_buffer_uptodate(io_tree, eb) &&
+       lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
+                        0, &cached_state, GFP_NOFS);
+       if (extent_buffer_uptodate(io_tree, eb, cached_state) &&
            btrfs_header_generation(eb) == parent_transid) {
                ret = 0;
                goto out;
@@ -282,10 +283,10 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
                       (unsigned long long)btrfs_header_generation(eb));
        }
        ret = 1;
-       clear_extent_buffer_uptodate(io_tree, eb);
+       clear_extent_buffer_uptodate(io_tree, eb, &cached_state);
 out:
-       unlock_extent(io_tree, eb->start, eb->start + eb->len - 1,
-                     GFP_NOFS);
+       unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1,
+                            &cached_state, GFP_NOFS);
        return ret;
 }
 
@@ -773,7 +774,7 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
        }
 }
 
-static struct address_space_operations btree_aops = {
+static const struct address_space_operations btree_aops = {
        .readpage       = btree_readpage,
        .writepage      = btree_writepage,
        .writepages     = btree_writepages,
@@ -822,16 +823,14 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
 
 int btrfs_write_tree_block(struct extent_buffer *buf)
 {
-       return btrfs_fdatawrite_range(buf->first_page->mapping, buf->start,
-                                     buf->start + buf->len - 1, WB_SYNC_ALL);
+       return filemap_fdatawrite_range(buf->first_page->mapping, buf->start,
+                                       buf->start + buf->len - 1);
 }
 
 int btrfs_wait_tree_block_writeback(struct extent_buffer *buf)
 {
-       return btrfs_wait_on_page_writeback_range(buf->first_page->mapping,
-                                 buf->start >> PAGE_CACHE_SHIFT,
-                                 (buf->start + buf->len - 1) >>
-                                  PAGE_CACHE_SHIFT);
+       return filemap_fdatawait_range(buf->first_page->mapping,
+                                      buf->start, buf->start + buf->len - 1);
 }
 
 struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
@@ -894,6 +893,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        root->stripesize = stripesize;
        root->ref_cows = 0;
        root->track_dirty = 0;
+       root->in_radix = 0;
+       root->clean_orphans = 0;
 
        root->fs_info = fs_info;
        root->objectid = objectid;
@@ -901,7 +902,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        root->highest_objectid = 0;
        root->name = NULL;
        root->in_sysfs = 0;
-       root->inode_tree.rb_node = NULL;
+       root->inode_tree = RB_ROOT;
 
        INIT_LIST_HEAD(&root->dirty_list);
        INIT_LIST_HEAD(&root->orphan_list);
@@ -930,7 +931,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        root->defrag_trans_start = fs_info->generation;
        init_completion(&root->kobj_unregister);
        root->defrag_running = 0;
-       root->defrag_level = 0;
        root->root_key.objectid = objectid;
        root->anon_super.s_root = NULL;
        root->anon_super.s_dev = 0;
@@ -982,12 +982,12 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
 
        while (1) {
                ret = find_first_extent_bit(&log_root_tree->dirty_log_pages,
-                                   0, &start, &end, EXTENT_DIRTY);
+                               0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
                if (ret)
                        break;
 
-               clear_extent_dirty(&log_root_tree->dirty_log_pages,
-                                  start, end, GFP_NOFS);
+               clear_extent_bits(&log_root_tree->dirty_log_pages, start, end,
+                                 EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
        }
        eb = fs_info->log_root_tree->node;
 
@@ -1212,8 +1212,10 @@ again:
        ret = radix_tree_insert(&fs_info->fs_roots_radix,
                                (unsigned long)root->root_key.objectid,
                                root);
-       if (ret == 0)
+       if (ret == 0) {
                root->in_radix = 1;
+               root->clean_orphans = 1;
+       }
        spin_unlock(&fs_info->fs_roots_radix_lock);
        radix_tree_preload_end();
        if (ret) {
@@ -1227,10 +1229,6 @@ again:
        ret = btrfs_find_dead_roots(fs_info->tree_root,
                                    root->root_key.objectid);
        WARN_ON(ret);
-
-       if (!(fs_info->sb->s_flags & MS_RDONLY))
-               btrfs_orphan_cleanup(root);
-
        return root;
 fail:
        free_fs_root(root);
@@ -1376,17 +1374,10 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi)
        int err;
 
        bdi->capabilities = BDI_CAP_MAP_COPY;
-       err = bdi_init(bdi);
+       err = bdi_setup_and_register(bdi, "btrfs", BDI_CAP_MAP_COPY);
        if (err)
                return err;
 
-       err = bdi_register(bdi, NULL, "btrfs-%d",
-                               atomic_inc_return(&btrfs_bdi_num));
-       if (err) {
-               bdi_destroy(bdi);
-               return err;
-       }
-
        bdi->ra_pages   = default_backing_dev_info.ra_pages;
        bdi->unplug_io_fn       = btrfs_unplug_io_fn;
        bdi->unplug_io_data     = info;
@@ -1478,6 +1469,7 @@ static int cleaner_kthread(void *arg)
 
                if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
                    mutex_trylock(&root->fs_info->cleaner_mutex)) {
+                       btrfs_run_delayed_iputs(root);
                        btrfs_clean_old_snapshots(root);
                        mutex_unlock(&root->fs_info->cleaner_mutex);
                }
@@ -1607,6 +1599,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
        INIT_LIST_HEAD(&fs_info->trans_list);
        INIT_LIST_HEAD(&fs_info->dead_roots);
+       INIT_LIST_HEAD(&fs_info->delayed_iputs);
        INIT_LIST_HEAD(&fs_info->hashers);
        INIT_LIST_HEAD(&fs_info->delalloc_inodes);
        INIT_LIST_HEAD(&fs_info->ordered_operations);
@@ -1615,6 +1608,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        spin_lock_init(&fs_info->new_trans_lock);
        spin_lock_init(&fs_info->ref_cache_lock);
        spin_lock_init(&fs_info->fs_roots_radix_lock);
+       spin_lock_init(&fs_info->delayed_iput_lock);
 
        init_completion(&fs_info->kobj_unregister);
        fs_info->tree_root = tree_root;
@@ -1631,7 +1625,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        atomic_set(&fs_info->async_submit_draining, 0);
        atomic_set(&fs_info->nr_async_bios, 0);
        fs_info->sb = sb;
-       fs_info->max_extent = (u64)-1;
        fs_info->max_inline = 8192 * 1024;
        fs_info->metadata_ratio = 0;
 
@@ -1643,6 +1636,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 
        sb->s_blocksize = 4096;
        sb->s_blocksize_bits = blksize_bits(4096);
+       sb->s_bdi = &fs_info->bdi;
 
        fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID;
        fs_info->btree_inode->i_nlink = 1;
@@ -1671,7 +1665,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        insert_inode_hash(fs_info->btree_inode);
 
        spin_lock_init(&fs_info->block_group_cache_lock);
-       fs_info->block_group_cache_tree.rb_node = NULL;
+       fs_info->block_group_cache_tree = RB_ROOT;
 
        extent_io_tree_init(&fs_info->freed_extents[0],
                             fs_info->btree_inode->i_mapping, GFP_NOFS);
@@ -1689,6 +1683,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        mutex_init(&fs_info->cleaner_mutex);
        mutex_init(&fs_info->volume_mutex);
        init_rwsem(&fs_info->extent_commit_sem);
+       init_rwsem(&fs_info->cleanup_work_sem);
        init_rwsem(&fs_info->subvol_sem);
 
        btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
@@ -1917,7 +1912,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 
        csum_root->track_dirty = 1;
 
-       btrfs_read_block_groups(extent_root);
+       ret = btrfs_read_block_groups(extent_root);
+       if (ret) {
+               printk(KERN_ERR "Failed to read block groups: %d\n", ret);
+               goto fail_block_groups;
+       }
 
        fs_info->generation = generation;
        fs_info->last_trans_committed = generation;
@@ -1927,7 +1926,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
                                               "btrfs-cleaner");
        if (IS_ERR(fs_info->cleaner_kthread))
-               goto fail_csum_root;
+               goto fail_block_groups;
 
        fs_info->transaction_kthread = kthread_run(transaction_kthread,
                                                   tree_root,
@@ -1979,7 +1978,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 
        if (!(sb->s_flags & MS_RDONLY)) {
                ret = btrfs_recover_relocation(tree_root);
-               BUG_ON(ret);
+               if (ret < 0) {
+                       printk(KERN_WARNING
+                              "btrfs: failed to recover relocation\n");
+                       err = -EINVAL;
+                       goto fail_trans_kthread;
+               }
        }
 
        location.objectid = BTRFS_FS_TREE_OBJECTID;
@@ -1990,6 +1994,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        if (!fs_info->fs_root)
                goto fail_trans_kthread;
 
+       if (!(sb->s_flags & MS_RDONLY)) {
+               down_read(&fs_info->cleanup_work_sem);
+               btrfs_orphan_cleanup(fs_info->fs_root);
+               up_read(&fs_info->cleanup_work_sem);
+       }
+
        return tree_root;
 
 fail_trans_kthread:
@@ -2004,7 +2014,8 @@ fail_cleaner:
        filemap_write_and_wait(fs_info->btree_inode->i_mapping);
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
 
-fail_csum_root:
+fail_block_groups:
+       btrfs_free_block_groups(fs_info);
        free_extent_buffer(csum_root->node);
        free_extent_buffer(csum_root->commit_root);
 fail_dev_root:
@@ -2386,8 +2397,14 @@ int btrfs_commit_super(struct btrfs_root *root)
        int ret;
 
        mutex_lock(&root->fs_info->cleaner_mutex);
+       btrfs_run_delayed_iputs(root);
        btrfs_clean_old_snapshots(root);
        mutex_unlock(&root->fs_info->cleaner_mutex);
+
+       /* wait until ongoing cleanup work done */
+       down_write(&root->fs_info->cleanup_work_sem);
+       up_write(&root->fs_info->cleanup_work_sem);
+
        trans = btrfs_start_transaction(root, 1);
        ret = btrfs_commit_transaction(trans, root);
        BUG_ON(ret);
@@ -2477,7 +2494,8 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
        int ret;
        struct inode *btree_inode = buf->first_page->mapping->host;
 
-       ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf);
+       ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf,
+                                    NULL);
        if (!ret)
                return ret;