#include <linux/scatterlist.h>
#include <linux/swap.h>
#include <linux/radix-tree.h>
+#include <linux/writeback.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
} while (bh != head);
out_unlock:
unlock_page(page);
- if (ret) {
- touch_buffer(ret);
- }
page_cache_release(page);
return ret;
}
ret = crypto_hash_digest(&desc, &sg, 1, result);
spin_unlock(&root->fs_info->hash_lock);
if (ret) {
- printk("sha256 digest failed\n");
+ printk("digest failed\n");
}
return ret;
}
static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh,
int verify)
{
- char result[BTRFS_CSUM_SIZE];
+ char result[BTRFS_CRC32_SIZE];
int ret;
struct btrfs_node *node;
if (ret)
return ret;
if (verify) {
- if (memcmp(bh->b_data, result, BTRFS_CSUM_SIZE)) {
+ if (memcmp(bh->b_data, result, BTRFS_CRC32_SIZE)) {
printk("checksum verify failed on %Lu\n",
bh_blocknr(bh));
return 1;
}
} else {
node = btrfs_buffer_node(bh);
- memcpy(node->header.csum, result, BTRFS_CSUM_SIZE);
+ memcpy(node->header.csum, result, BTRFS_CRC32_SIZE);
}
return 0;
}
.sync_page = block_sync_page,
};
+int readahead_tree_block(struct btrfs_root *root, u64 blocknr)
+{
+ struct buffer_head *bh = NULL;
+ int ret = 0;
+
+ bh = btrfs_find_create_tree_block(root, blocknr);
+ if (!bh)
+ return 0;
+ if (buffer_uptodate(bh)) {
+ ret = 1;
+ goto done;
+ }
+ if (test_set_buffer_locked(bh)) {
+ ret = 1;
+ goto done;
+ }
+ if (!buffer_uptodate(bh)) {
+ get_bh(bh);
+ bh->b_end_io = end_buffer_read_sync;
+ submit_bh(READ, bh);
+ } else {
+ unlock_buffer(bh);
+ ret = 1;
+ }
+done:
+ brelse(bh);
+ return ret;
+}
+
struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
{
struct buffer_head *bh = NULL;
wait_on_buffer(bh);
if (!buffer_uptodate(bh))
goto fail;
- csum_tree_block(root, bh, 1);
} else {
unlock_buffer(bh);
}
uptodate:
+ if (!buffer_checked(bh)) {
+ csum_tree_block(root, bh, 1);
+ set_buffer_checked(bh);
+ }
if (check_tree_block(root, bh))
BUG();
return bh;
init_bit_radix(&fs_info->pinned_radix);
init_bit_radix(&fs_info->pending_del_radix);
+ init_bit_radix(&fs_info->extent_map_radix);
INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS);
INIT_RADIX_TREE(&fs_info->dev_radix, GFP_NOFS);
+ INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL);
+ INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL);
INIT_LIST_HEAD(&fs_info->trans_list);
+ INIT_LIST_HEAD(&fs_info->dead_roots);
sb_set_blocksize(sb, 4096);
fs_info->running_transaction = NULL;
fs_info->tree_root = tree_root;
fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size;
fs_info->btree_inode->i_mapping->a_ops = &btree_aops;
fs_info->do_barriers = 1;
+ fs_info->extent_tree_insert_nr = 0;
+ fs_info->extent_tree_prealloc_nr = 0;
+ fs_info->closing = 0;
+
+ INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
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);
- fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
+ fs_info->hash_tfm = crypto_alloc_hash("crc32c", 0, CRYPTO_ALG_ASYNC);
spin_lock_init(&fs_info->hash_lock);
if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) {
- printk("failed to allocate sha256 hash\n");
+ printk("failed to allocate digest hash\n");
return NULL;
}
mutex_init(&fs_info->trans_mutex);
mutex_init(&fs_info->fs_mutex);
- memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert));
- memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert));
__setup_root(sb->s_blocksize, dev_root,
fs_info, BTRFS_DEV_TREE_OBJECTID);
BTRFS_EXTENT_TREE_OBJECTID, extent_root);
BUG_ON(ret);
+ btrfs_read_block_groups(extent_root);
+
fs_info->generation = btrfs_super_generation(disk_super) + 1;
- memset(&fs_info->kobj, 0, sizeof(fs_info->kobj));
- kobj_set_kset_s(fs_info, btrfs_subsys);
- kobject_set_name(&fs_info->kobj, "%s", sb->s_id);
- kobject_register(&fs_info->kobj);
mutex_unlock(&fs_info->fs_mutex);
return tree_root;
}
return 0;
}
-int del_fs_roots(struct btrfs_fs_info *fs_info)
+static int del_fs_roots(struct btrfs_fs_info *fs_info)
{
int ret;
struct btrfs_root *gang[8];
struct btrfs_trans_handle *trans;
struct btrfs_fs_info *fs_info = root->fs_info;
+ fs_info->closing = 1;
+ btrfs_transaction_flush_work(root);
mutex_lock(&fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1);
btrfs_commit_transaction(trans, root);
iput(fs_info->btree_inode);
free_dev_radix(fs_info);
+ btrfs_free_block_groups(root->fs_info);
del_fs_roots(fs_info);
kfree(fs_info->extent_root);
kfree(fs_info->tree_root);
- kobject_unregister(&fs_info->kobj);
return 0;
}
brelse(buf);
}
+void btrfs_btree_balance_dirty(struct btrfs_root *root)
+{
+ balance_dirty_pages_ratelimited(root->fs_info->btree_inode->i_mapping);
+}