#include <linux/buffer_head.h> // for block_sync_page
#include <linux/workqueue.h>
#include <linux/kthread.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
# include <linux/freezer.h>
-#else
-# include <linux/sched.h>
-#endif
#include "crc32c.h"
#include "ctree.h"
#include "disk-io.h"
return 0;
}
-static int btree_writepage_io_hook(struct page *page, u64 start, u64 end)
-{
- struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
-
- csum_dirty_buffer(root, page);
- return 0;
-}
-
int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
struct extent_state *state)
{
eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS);
found_start = btrfs_header_bytenr(eb);
- if (0 && found_start != start) {
+ if (found_start != start) {
printk("bad tree block start %llu %llu\n",
(unsigned long long)found_start,
(unsigned long long)eb->start);
return ret;
}
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
static void end_workqueue_bio(struct bio *bio, int err)
-#else
-static int end_workqueue_bio(struct bio *bio,
- unsigned int bytes_done, int err)
-#endif
{
struct end_io_wq *end_io_wq = bio->bi_private;
struct btrfs_fs_info *fs_info;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
- if (bio->bi_size)
- return 1;
-#endif
-
fs_info = end_io_wq->info;
end_io_wq->error = err;
end_io_wq->work.func = end_workqueue_fn;
&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;
-#endif
}
int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
async->submit_bio_hook = submit_bio_hook;
async->work.func = run_one_async_submit;
async->work.flags = 0;
+
+ while(atomic_read(&fs_info->async_submit_draining) &&
+ atomic_read(&fs_info->nr_async_submits)) {
+ wait_event(fs_info->async_submit_wait,
+ (atomic_read(&fs_info->nr_async_submits) == 0));
+ }
+
atomic_inc(&fs_info->nr_async_submits);
btrfs_queue_worker(&fs_info->workers, &async->work);
return 0;
}
+static int btree_csum_one_bio(struct bio *bio)
+{
+ struct bio_vec *bvec = bio->bi_io_vec;
+ int bio_index = 0;
+ struct btrfs_root *root;
+
+ WARN_ON(bio->bi_vcnt <= 0);
+ while(bio_index < bio->bi_vcnt) {
+ root = BTRFS_I(bvec->bv_page->mapping->host)->root;
+ csum_dirty_buffer(root, bvec->bv_page);
+ bio_index++;
+ bvec++;
+ }
+ return 0;
+}
+
static int __btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
int mirror_num)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
- u64 offset;
int ret;
- offset = bio->bi_sector << 9;
-
/*
* when we're called for a write, we're already in the async
* submission context. Just jump into btrfs_map_bio
*/
if (rw & (1 << BIO_RW)) {
+ btree_csum_one_bio(bio);
return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio,
mirror_num, 1);
}
if (wbc->sync_mode == WB_SYNC_NONE) {
u64 num_dirty;
u64 start = 0;
- unsigned long thresh = 8 * 1024 * 1024;
+ unsigned long thresh = 32 * 1024 * 1024;
if (wbc->for_kupdate)
return 0;
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_NONE);
+ buf->start + buf->len - 1, WB_SYNC_ALL);
}
int btrfs_wait_tree_block_writeback(struct extent_buffer *buf)
spin_lock_init(&root->list_lock);
mutex_init(&root->objectid_mutex);
mutex_init(&root->log_mutex);
+ extent_io_tree_init(&root->dirty_log_pages,
+ fs_info->btree_inode->i_mapping, GFP_NOFS);
btrfs_leaf_ref_tree_init(&root->ref_tree_struct);
root->ref_tree = &root->ref_tree_struct;
struct btrfs_fs_info *fs_info)
{
struct extent_buffer *eb;
+ struct btrfs_root *log_root_tree = fs_info->log_root_tree;
+ u64 start = 0;
+ u64 end = 0;
int ret;
- if (!fs_info->log_root_tree)
+ if (!log_root_tree)
return 0;
+ while(1) {
+ ret = find_first_extent_bit(&log_root_tree->dirty_log_pages,
+ 0, &start, &end, EXTENT_DIRTY);
+ if (ret)
+ break;
+
+ clear_extent_dirty(&log_root_tree->dirty_log_pages,
+ start, end, GFP_NOFS);
+ }
eb = fs_info->log_root_tree->node;
WARN_ON(btrfs_header_level(eb) != 0);
WARN_ON(btrfs_header_nritems(eb) != 0);
- ret = btrfs_free_extent(trans, fs_info->tree_root,
- eb->start, eb->len,
- BTRFS_TREE_LOG_OBJECTID, 0, 0, 0, 1);
+ ret = btrfs_free_reserved_extent(fs_info->tree_root,
+ eb->start, eb->len);
BUG_ON(ret);
free_extent_buffer(eb);
root->ref_cows = 0;
root->node = btrfs_alloc_free_block(trans, root, root->leafsize,
- BTRFS_TREE_LOG_OBJECTID,
- 0, 0, 0, 0, 0);
+ 0, BTRFS_TREE_LOG_OBJECTID,
+ trans->transid, 0, 0, 0);
btrfs_set_header_nritems(root->node, 0);
btrfs_set_header_level(root->node, 0);
static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi)
{
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
bdi_init(bdi);
-#endif
bdi->ra_pages = default_backing_dev_info.ra_pages;
bdi->state = 0;
bdi->capabilities = default_backing_dev_info.capabilities;
bio->bi_private = end_io_wq->private;
bio->bi_end_io = end_io_wq->end_io;
kfree(end_io_wq);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
- bio_endio(bio, bio->bi_size, error);
-#else
bio_endio(bio, error);
-#endif
}
static int cleaner_kthread(void *arg)
INIT_LIST_HEAD(&fs_info->space_info);
btrfs_mapping_init(&fs_info->mapping_tree);
atomic_set(&fs_info->nr_async_submits, 0);
+ atomic_set(&fs_info->async_submit_draining, 0);
atomic_set(&fs_info->nr_async_bios, 0);
atomic_set(&fs_info->throttles, 0);
atomic_set(&fs_info->throttle_gen, 0);
BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops;
- extent_io_tree_init(&fs_info->free_space_cache,
- fs_info->btree_inode->i_mapping, GFP_NOFS);
- extent_io_tree_init(&fs_info->block_group_cache,
- fs_info->btree_inode->i_mapping, GFP_NOFS);
+ spin_lock_init(&fs_info->block_group_cache_lock);
+ fs_info->block_group_cache_tree.rb_node = NULL;
+
extent_io_tree_init(&fs_info->pinned_extents,
fs_info->btree_inode->i_mapping, GFP_NOFS);
extent_io_tree_init(&fs_info->pending_del,
fs_info->btree_inode->i_mapping, GFP_NOFS);
fs_info->do_barriers = 1;
+ extent_io_tree_init(&fs_info->reloc_mapping_tree,
+ fs_info->btree_inode->i_mapping, GFP_NOFS);
+ INIT_LIST_HEAD(&fs_info->dead_reloc_roots);
+ btrfs_leaf_ref_tree_init(&fs_info->reloc_ref_tree);
+ btrfs_leaf_ref_tree_init(&fs_info->shared_ref_tree);
+
BTRFS_I(fs_info->btree_inode)->root = tree_root;
memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
sizeof(struct btrfs_key));
insert_inode_hash(fs_info->btree_inode);
- mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
mutex_init(&fs_info->trans_mutex);
mutex_init(&fs_info->tree_log_mutex);
mutex_init(&fs_info->transaction_kthread_mutex);
mutex_init(&fs_info->cleaner_mutex);
mutex_init(&fs_info->volume_mutex);
+ mutex_init(&fs_info->tree_reloc_mutex);
init_waitqueue_head(&fs_info->transaction_throttle);
init_waitqueue_head(&fs_info->transaction_wait);
init_waitqueue_head(&fs_info->async_submit_wait);
ret = btrfs_recover_log_trees(log_tree_root);
BUG_ON(ret);
}
+
+ ret = btrfs_cleanup_reloc_trees(tree_root);
+ BUG_ON(ret);
+
fs_info->last_trans_committed = btrfs_super_generation(disk_super);
return tree_root;
kfree(extent_root);
kfree(tree_root);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
bdi_destroy(&fs_info->bdi);
-#endif
kfree(fs_info);
return ERR_PTR(err);
}
btrfs_close_devices(fs_info->fs_devices);
btrfs_mapping_tree_free(&fs_info->mapping_tree);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
bdi_destroy(&fs_info->bdi);
-#endif
kfree(fs_info->extent_root);
kfree(fs_info->tree_root);
static struct extent_io_ops btree_extent_io_ops = {
.write_cache_pages_lock_hook = btree_lock_page_hook,
- .writepage_io_hook = btree_writepage_io_hook,
.readpage_end_io_hook = btree_readpage_end_io_hook,
.submit_bio_hook = btree_submit_bio_hook,
/* note we're sharing with inode.c for the merge bio hook */