aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 970103f2cacd..2afb7922b062 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1,6 +1,8 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/fs.h> 2#include <linux/fs.h>
3#include <linux/blkdev.h> 3#include <linux/blkdev.h>
4#include <linux/crypto.h>
5#include <linux/scatterlist.h>
4#include "ctree.h" 6#include "ctree.h"
5#include "disk-io.h" 7#include "disk-io.h"
6#include "transaction.h" 8#include "transaction.h"
@@ -126,8 +128,51 @@ static int btree_get_block(struct inode *inode, sector_t iblock,
126 return 0; 128 return 0;
127} 129}
128 130
131static int csum_tree_block(struct btrfs_root * root, struct buffer_head *bh,
132 int verify)
133{
134 struct btrfs_node *node = btrfs_buffer_node(bh);
135 struct scatterlist sg;
136 struct crypto_hash *tfm = root->fs_info->hash_tfm;
137 struct hash_desc desc;
138 int ret;
139 char result[32];
140
141 desc.tfm = tfm;
142 desc.flags = 0;
143 sg_init_one(&sg, bh->b_data + 32, bh->b_size - 32);
144 spin_lock(&root->fs_info->hash_lock);
145 ret = crypto_hash_digest(&desc, &sg, bh->b_size - 32, result);
146 spin_unlock(&root->fs_info->hash_lock);
147 if (ret) {
148 printk("sha256 digest failed\n");
149 }
150 if (verify) {
151 if (memcmp(node->header.csum, result, sizeof(result)))
152 printk("csum verify failed on %Lu\n", bh->b_blocknr);
153 return -EINVAL;
154 } else
155 memcpy(node->header.csum, result, sizeof(node->header.csum));
156 return 0;
157}
158
129static int btree_writepage(struct page *page, struct writeback_control *wbc) 159static int btree_writepage(struct page *page, struct writeback_control *wbc)
130{ 160{
161 struct buffer_head *bh;
162 struct btrfs_root *root = btrfs_sb(page->mapping->host->i_sb);
163 struct buffer_head *head;
164
165 if (!page_has_buffers(page)) {
166 create_empty_buffers(page, root->fs_info->sb->s_blocksize,
167 (1 << BH_Dirty)|(1 << BH_Uptodate));
168 }
169 head = page_buffers(page);
170 bh = head;
171 do {
172 if (buffer_dirty(bh))
173 csum_tree_block(root, bh, 0);
174 bh = bh->b_this_page;
175 } while (bh != head);
131 return block_write_full_page(page, btree_get_block, wbc); 176 return block_write_full_page(page, btree_get_block, wbc);
132} 177}
133 178
@@ -157,6 +202,7 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
157 wait_on_buffer(bh); 202 wait_on_buffer(bh);
158 if (!buffer_uptodate(bh)) 203 if (!buffer_uptodate(bh))
159 goto fail; 204 goto fail;
205 csum_tree_block(root, bh, 1);
160 } else { 206 } else {
161 unlock_buffer(bh); 207 unlock_buffer(bh);
162 } 208 }
@@ -233,8 +279,9 @@ struct btrfs_root *open_ctree(struct super_block *sb,
233 GFP_NOFS); 279 GFP_NOFS);
234 int ret; 280 int ret;
235 281
236 if (!btrfs_super_root(disk_super)) 282 if (!btrfs_super_root(disk_super)) {
237 return NULL; 283 return NULL;
284 }
238 init_bit_radix(&fs_info->pinned_radix); 285 init_bit_radix(&fs_info->pinned_radix);
239 init_bit_radix(&fs_info->pending_del_radix); 286 init_bit_radix(&fs_info->pending_del_radix);
240 sb_set_blocksize(sb, sb_buffer->b_size); 287 sb_set_blocksize(sb, sb_buffer->b_size);
@@ -252,6 +299,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,
252 fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 299 fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size;
253 fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 300 fs_info->btree_inode->i_mapping->a_ops = &btree_aops;
254 mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 301 mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
302 fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
303 if (!fs_info->hash_tfm) {
304 printk("failed to allocate sha256 hash\n");
305 return NULL;
306 }
307 spin_lock_init(&fs_info->hash_lock);
255 308
256 mutex_init(&fs_info->trans_mutex); 309 mutex_init(&fs_info->trans_mutex);
257 mutex_init(&fs_info->fs_mutex); 310 mutex_init(&fs_info->fs_mutex);
@@ -262,9 +315,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
262 315
263 fs_info->sb_buffer = read_tree_block(tree_root, sb_buffer->b_blocknr); 316 fs_info->sb_buffer = read_tree_block(tree_root, sb_buffer->b_blocknr);
264 317
265 if (!fs_info->sb_buffer) 318 if (!fs_info->sb_buffer) {
319printk("failed2\n");
266 return NULL; 320 return NULL;
267 321 }
268 brelse(sb_buffer); 322 brelse(sb_buffer);
269 sb_buffer = NULL; 323 sb_buffer = NULL;
270 disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; 324 disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data;
@@ -300,6 +354,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
300 root->fs_info->tree_root->node->b_blocknr); 354 root->fs_info->tree_root->node->b_blocknr);
301 lock_buffer(bh); 355 lock_buffer(bh);
302 clear_buffer_dirty(bh); 356 clear_buffer_dirty(bh);
357 csum_tree_block(root, bh, 0);
303 bh->b_end_io = end_buffer_write_sync; 358 bh->b_end_io = end_buffer_write_sync;
304 get_bh(bh); 359 get_bh(bh);
305 submit_bh(WRITE, bh); 360 submit_bh(WRITE, bh);
@@ -338,6 +393,7 @@ int close_ctree(struct btrfs_root *root)
338 root->fs_info->tree_root->node); 393 root->fs_info->tree_root->node);
339 btrfs_block_release(root, root->commit_root); 394 btrfs_block_release(root, root->commit_root);
340 btrfs_block_release(root, root->fs_info->sb_buffer); 395 btrfs_block_release(root, root->fs_info->sb_buffer);
396 crypto_free_hash(root->fs_info->hash_tfm);
341 iput(root->fs_info->btree_inode); 397 iput(root->fs_info->btree_inode);
342 kfree(root->fs_info->extent_root); 398 kfree(root->fs_info->extent_root);
343 kfree(root->fs_info->inode_root); 399 kfree(root->fs_info->inode_root);