Btrfs: Search data ordered extents first for checksums on read
[linux-2.6-block.git] / fs / btrfs / disk-io.c
index 4cdc0b6a26726d6f0009814212060222dd446433..7ce3f83c5dd633bab76b3a535361b28013b134d3 100644 (file)
@@ -381,7 +381,6 @@ int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
 
        end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
        end = eb->start + end - 1;
-       release_extent_buffer_tail_pages(eb);
 err:
        free_extent_buffer(eb);
 out:
@@ -407,7 +406,11 @@ static int end_workqueue_bio(struct bio *bio,
        end_io_wq->error = err;
        end_io_wq->work.func = end_workqueue_fn;
        end_io_wq->work.flags = 0;
-       btrfs_queue_worker(&fs_info->endio_workers, &end_io_wq->work);
+       if (bio->bi_rw & (1 << BIO_RW))
+               btrfs_queue_worker(&fs_info->endio_write_workers,
+                                  &end_io_wq->work);
+       else
+               btrfs_queue_worker(&fs_info->endio_workers, &end_io_wq->work);
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
        return 0;
@@ -559,21 +562,21 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags)
        struct extent_map_tree *map;
        int ret;
 
-       if (page_count(page) > 3) {
-               /* once for page->private, once for the caller, once
-                * once for the page cache
-                */
-               return 0;
-       }
        tree = &BTRFS_I(page->mapping->host)->io_tree;
        map = &BTRFS_I(page->mapping->host)->extent_tree;
+
        ret = try_release_extent_state(map, tree, page, gfp_flags);
+       if (!ret) {
+               return 0;
+       }
+
+       ret = try_release_extent_buffer(tree, page);
        if (ret == 1) {
-               invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
                ClearPagePrivate(page);
                set_page_private(page, 0);
                page_cache_release(page);
        }
+
        return ret;
 }
 
@@ -584,7 +587,8 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
        extent_invalidatepage(tree, page, offset);
        btree_releasepage(page, GFP_NOFS);
        if (PagePrivate(page)) {
-               invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
+               printk("warning page private not zero on page %Lu\n",
+                      page_offset(page));
                ClearPagePrivate(page);
                set_page_private(page, 0);
                page_cache_release(page);
@@ -1007,9 +1011,16 @@ void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
        spin_lock(&em_tree->lock);
        em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE);
        spin_unlock(&em_tree->lock);
-       if (!em)
+       if (!em) {
+               __unplug_io_fn(bdi, page);
                return;
+       }
 
+       if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
+               free_extent_map(em);
+               __unplug_io_fn(bdi, page);
+               return;
+       }
        offset = offset - em->start;
        btrfs_unplug_page(&BTRFS_I(inode)->root->fs_info->mapping_tree,
                          em->block_start + offset, page);
@@ -1117,9 +1128,7 @@ static int cleaner_kthread(void *arg)
 
                vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
                mutex_lock(&root->fs_info->cleaner_mutex);
-printk("cleaner awake\n");
                btrfs_clean_old_snapshots(root);
-printk("cleaner done\n");
                mutex_unlock(&root->fs_info->cleaner_mutex);
 
                if (freezing(current)) {
@@ -1287,6 +1296,9 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        mutex_init(&fs_info->chunk_mutex);
        mutex_init(&fs_info->transaction_kthread_mutex);
        mutex_init(&fs_info->cleaner_mutex);
+       mutex_init(&fs_info->volume_mutex);
+       init_waitqueue_head(&fs_info->transaction_throttle);
+       init_waitqueue_head(&fs_info->transaction_wait);
 
 #if 0
        ret = add_hasher(fs_info, "crc32c");
@@ -1325,10 +1337,16 @@ struct btrfs_root *open_ctree(struct super_block *sb,
         */
        btrfs_init_workers(&fs_info->workers, fs_info->thread_pool_size);
        btrfs_init_workers(&fs_info->submit_workers, fs_info->thread_pool_size);
+       btrfs_init_workers(&fs_info->fixup_workers, 1);
        btrfs_init_workers(&fs_info->endio_workers, fs_info->thread_pool_size);
+       btrfs_init_workers(&fs_info->endio_write_workers,
+                          fs_info->thread_pool_size);
        btrfs_start_workers(&fs_info->workers, 1);
        btrfs_start_workers(&fs_info->submit_workers, 1);
+       btrfs_start_workers(&fs_info->fixup_workers, 1);
        btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size);
+       btrfs_start_workers(&fs_info->endio_write_workers,
+                           fs_info->thread_pool_size);
 
        err = -EINVAL;
        if (btrfs_super_num_devices(disk_super) > fs_devices->open_devices) {
@@ -1445,9 +1463,10 @@ fail_tree_root:
        free_extent_buffer(tree_root->node);
 fail_sys_array:
 fail_sb_buffer:
-       extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree);
+       btrfs_stop_workers(&fs_info->fixup_workers);
        btrfs_stop_workers(&fs_info->workers);
        btrfs_stop_workers(&fs_info->endio_workers);
+       btrfs_stop_workers(&fs_info->endio_write_workers);
        btrfs_stop_workers(&fs_info->submit_workers);
 fail_iput:
        iput(fs_info->btree_inode);
@@ -1692,17 +1711,12 @@ int close_ctree(struct btrfs_root *root)
 
        filemap_write_and_wait(fs_info->btree_inode->i_mapping);
 
-       extent_io_tree_empty_lru(&fs_info->free_space_cache);
-       extent_io_tree_empty_lru(&fs_info->block_group_cache);
-       extent_io_tree_empty_lru(&fs_info->pinned_extents);
-       extent_io_tree_empty_lru(&fs_info->pending_del);
-       extent_io_tree_empty_lru(&fs_info->extent_ins);
-       extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree);
-
        truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
 
+       btrfs_stop_workers(&fs_info->fixup_workers);
        btrfs_stop_workers(&fs_info->workers);
        btrfs_stop_workers(&fs_info->endio_workers);
+       btrfs_stop_workers(&fs_info->endio_write_workers);
        btrfs_stop_workers(&fs_info->submit_workers);
 
        iput(fs_info->btree_inode);