aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:15:53 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commitdb94535db75e67fab12ccbb7f5ee548e33fed891 (patch)
tree1ad7dfc82b003294a94ee87d7329b24b902b369f /fs/btrfs/disk-io.c
parent1a5bc167f6707542b79a55452075525620ed43f5 (diff)
Btrfs: Allow tree blocks larger than the page size
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c92
1 files changed, 58 insertions, 34 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 2b86a1d779b7..fad9298c6962 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -28,6 +28,7 @@
28#include "disk-io.h" 28#include "disk-io.h"
29#include "transaction.h" 29#include "transaction.h"
30#include "btrfs_inode.h" 30#include "btrfs_inode.h"
31#include "print-tree.h"
31 32
32#if 0 33#if 0
33static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) 34static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
@@ -43,26 +44,25 @@ static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
43#endif 44#endif
44 45
45struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, 46struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
46 u64 blocknr) 47 u64 bytenr, u32 blocksize)
47{ 48{
48 struct inode *btree_inode = root->fs_info->btree_inode; 49 struct inode *btree_inode = root->fs_info->btree_inode;
49 struct extent_buffer *eb; 50 struct extent_buffer *eb;
50 eb = find_extent_buffer(&BTRFS_I(btree_inode)->extent_tree, 51 eb = find_extent_buffer(&BTRFS_I(btree_inode)->extent_tree,
51 blocknr * root->sectorsize, 52 bytenr, blocksize, GFP_NOFS);
52 root->sectorsize, GFP_NOFS);
53 if (eb) 53 if (eb)
54 eb->alloc_addr = (unsigned long)__builtin_return_address(0); 54 eb->alloc_addr = (unsigned long)__builtin_return_address(0);
55 return eb; 55 return eb;
56} 56}
57 57
58struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, 58struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
59 u64 blocknr) 59 u64 bytenr, u32 blocksize)
60{ 60{
61 struct inode *btree_inode = root->fs_info->btree_inode; 61 struct inode *btree_inode = root->fs_info->btree_inode;
62 struct extent_buffer *eb; 62 struct extent_buffer *eb;
63
63 eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_tree, 64 eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_tree,
64 blocknr * root->sectorsize, 65 bytenr, blocksize, GFP_NOFS);
65 root->sectorsize, GFP_NOFS);
66 eb->alloc_addr = (unsigned long)__builtin_return_address(0); 66 eb->alloc_addr = (unsigned long)__builtin_return_address(0);
67 return eb; 67 return eb;
68} 68}
@@ -208,13 +208,13 @@ static struct address_space_operations btree_aops = {
208 .sync_page = block_sync_page, 208 .sync_page = block_sync_page,
209}; 209};
210 210
211int readahead_tree_block(struct btrfs_root *root, u64 blocknr) 211int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
212{ 212{
213 struct extent_buffer *buf = NULL; 213 struct extent_buffer *buf = NULL;
214 struct inode *btree_inode = root->fs_info->btree_inode; 214 struct inode *btree_inode = root->fs_info->btree_inode;
215 int ret = 0; 215 int ret = 0;
216 216
217 buf = btrfs_find_create_tree_block(root, blocknr); 217 buf = btrfs_find_create_tree_block(root, bytenr, blocksize);
218 if (!buf) 218 if (!buf)
219 return 0; 219 return 0;
220 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 220 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
@@ -223,12 +223,13 @@ int readahead_tree_block(struct btrfs_root *root, u64 blocknr)
223 return ret; 223 return ret;
224} 224}
225 225
226struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) 226struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
227 u32 blocksize)
227{ 228{
228 struct extent_buffer *buf = NULL; 229 struct extent_buffer *buf = NULL;
229 struct inode *btree_inode = root->fs_info->btree_inode; 230 struct inode *btree_inode = root->fs_info->btree_inode;
230 231
231 buf = btrfs_find_create_tree_block(root, blocknr); 232 buf = btrfs_find_create_tree_block(root, bytenr, blocksize);
232 if (!buf) 233 if (!buf)
233 return NULL; 234 return NULL;
234 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 235 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
@@ -261,7 +262,7 @@ int set_tree_block_dirty(struct btrfs_root *root, struct extent_buffer *buf)
261 return 0; 262 return 0;
262} 263}
263 264
264static int __setup_root(int blocksize, 265static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
265 struct btrfs_root *root, 266 struct btrfs_root *root,
266 struct btrfs_fs_info *fs_info, 267 struct btrfs_fs_info *fs_info,
267 u64 objectid) 268 u64 objectid)
@@ -269,9 +270,9 @@ static int __setup_root(int blocksize,
269 root->node = NULL; 270 root->node = NULL;
270 root->inode = NULL; 271 root->inode = NULL;
271 root->commit_root = NULL; 272 root->commit_root = NULL;
272 root->sectorsize = blocksize; 273 root->sectorsize = sectorsize;
273 root->nodesize = blocksize; 274 root->nodesize = nodesize;
274 root->leafsize = blocksize; 275 root->leafsize = leafsize;
275 root->ref_cows = 0; 276 root->ref_cows = 0;
276 root->fs_info = fs_info; 277 root->fs_info = fs_info;
277 root->objectid = objectid; 278 root->objectid = objectid;
@@ -291,21 +292,23 @@ static int __setup_root(int blocksize,
291 return 0; 292 return 0;
292} 293}
293 294
294static int find_and_setup_root(int blocksize, 295static int find_and_setup_root(struct btrfs_root *tree_root,
295 struct btrfs_root *tree_root,
296 struct btrfs_fs_info *fs_info, 296 struct btrfs_fs_info *fs_info,
297 u64 objectid, 297 u64 objectid,
298 struct btrfs_root *root) 298 struct btrfs_root *root)
299{ 299{
300 int ret; 300 int ret;
301 u32 blocksize;
301 302
302 __setup_root(blocksize, root, fs_info, objectid); 303 __setup_root(tree_root->nodesize, tree_root->leafsize,
304 tree_root->sectorsize, root, fs_info, objectid);
303 ret = btrfs_find_last_root(tree_root, objectid, 305 ret = btrfs_find_last_root(tree_root, objectid,
304 &root->root_item, &root->root_key); 306 &root->root_item, &root->root_key);
305 BUG_ON(ret); 307 BUG_ON(ret);
306 308
307 root->node = read_tree_block(root, 309 blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
308 btrfs_root_blocknr(&root->root_item)); 310 root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
311 blocksize);
309 BUG_ON(!root->node); 312 BUG_ON(!root->node);
310 return 0; 313 return 0;
311} 314}
@@ -318,14 +321,14 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
318 struct btrfs_path *path; 321 struct btrfs_path *path;
319 struct extent_buffer *l; 322 struct extent_buffer *l;
320 u64 highest_inode; 323 u64 highest_inode;
324 u32 blocksize;
321 int ret = 0; 325 int ret = 0;
322 326
323 root = kzalloc(sizeof(*root), GFP_NOFS); 327 root = kzalloc(sizeof(*root), GFP_NOFS);
324 if (!root) 328 if (!root)
325 return ERR_PTR(-ENOMEM); 329 return ERR_PTR(-ENOMEM);
326 if (location->offset == (u64)-1) { 330 if (location->offset == (u64)-1) {
327 ret = find_and_setup_root(fs_info->sb->s_blocksize, 331 ret = find_and_setup_root(tree_root, fs_info,
328 fs_info->tree_root, fs_info,
329 location->objectid, root); 332 location->objectid, root);
330 if (ret) { 333 if (ret) {
331 kfree(root); 334 kfree(root);
@@ -334,7 +337,8 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
334 goto insert; 337 goto insert;
335 } 338 }
336 339
337 __setup_root(fs_info->sb->s_blocksize, root, fs_info, 340 __setup_root(tree_root->nodesize, tree_root->leafsize,
341 tree_root->sectorsize, root, fs_info,
338 location->objectid); 342 location->objectid);
339 343
340 path = btrfs_alloc_path(); 344 path = btrfs_alloc_path();
@@ -357,8 +361,9 @@ out:
357 kfree(root); 361 kfree(root);
358 return ERR_PTR(ret); 362 return ERR_PTR(ret);
359 } 363 }
360 root->node = read_tree_block(root, 364 blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
361 btrfs_root_blocknr(&root->root_item)); 365 root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
366 blocksize);
362 BUG_ON(!root->node); 367 BUG_ON(!root->node);
363insert: 368insert:
364 root->ref_cows = 1; 369 root->ref_cows = 1;
@@ -418,6 +423,10 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
418 423
419struct btrfs_root *open_ctree(struct super_block *sb) 424struct btrfs_root *open_ctree(struct super_block *sb)
420{ 425{
426 u32 sectorsize;
427 u32 nodesize;
428 u32 leafsize;
429 u32 blocksize;
421 struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 430 struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root),
422 GFP_NOFS); 431 GFP_NOFS);
423 struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 432 struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root),
@@ -474,12 +483,12 @@ struct btrfs_root *open_ctree(struct super_block *sb)
474 mutex_init(&fs_info->trans_mutex); 483 mutex_init(&fs_info->trans_mutex);
475 mutex_init(&fs_info->fs_mutex); 484 mutex_init(&fs_info->fs_mutex);
476 485
477 __setup_root(sb->s_blocksize, tree_root, 486 __setup_root(512, 512, 512, tree_root,
478 fs_info, BTRFS_ROOT_TREE_OBJECTID); 487 fs_info, BTRFS_ROOT_TREE_OBJECTID);
479 488
480 fs_info->sb_buffer = read_tree_block(tree_root, 489 fs_info->sb_buffer = read_tree_block(tree_root,
481 BTRFS_SUPER_INFO_OFFSET / 490 BTRFS_SUPER_INFO_OFFSET,
482 sb->s_blocksize); 491 512);
483 492
484 if (!fs_info->sb_buffer) 493 if (!fs_info->sb_buffer)
485 goto fail_iput; 494 goto fail_iput;
@@ -494,9 +503,15 @@ struct btrfs_root *open_ctree(struct super_block *sb)
494 if (!btrfs_super_root(disk_super)) 503 if (!btrfs_super_root(disk_super))
495 goto fail_sb_buffer; 504 goto fail_sb_buffer;
496 505
506 nodesize = btrfs_super_nodesize(disk_super);
507 leafsize = btrfs_super_leafsize(disk_super);
508 sectorsize = btrfs_super_sectorsize(disk_super);
509 tree_root->nodesize = nodesize;
510 tree_root->leafsize = leafsize;
511 tree_root->sectorsize = sectorsize;
512
497 i_size_write(fs_info->btree_inode, 513 i_size_write(fs_info->btree_inode,
498 btrfs_super_total_blocks(disk_super) << 514 btrfs_super_total_bytes(disk_super));
499 fs_info->btree_inode->i_blkbits);
500 515
501 516
502 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, 517 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC,
@@ -504,13 +519,22 @@ struct btrfs_root *open_ctree(struct super_block *sb)
504 printk("btrfs: valid FS not found on %s\n", sb->s_id); 519 printk("btrfs: valid FS not found on %s\n", sb->s_id);
505 goto fail_sb_buffer; 520 goto fail_sb_buffer;
506 } 521 }
522 blocksize = btrfs_level_size(tree_root,
523 btrfs_super_root_level(disk_super));
507 tree_root->node = read_tree_block(tree_root, 524 tree_root->node = read_tree_block(tree_root,
508 btrfs_super_root(disk_super)); 525 btrfs_super_root(disk_super),
526 blocksize);
509 if (!tree_root->node) 527 if (!tree_root->node)
510 goto fail_sb_buffer; 528 goto fail_sb_buffer;
511 529
530#if 0
531 btrfs_print_leaf(tree_root, tree_root->node);
532 err = -EIO;
533 goto fail_tree_root;
534#endif
512 mutex_lock(&fs_info->fs_mutex); 535 mutex_lock(&fs_info->fs_mutex);
513 ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, 536
537 ret = find_and_setup_root(tree_root, fs_info,
514 BTRFS_EXTENT_TREE_OBJECTID, extent_root); 538 BTRFS_EXTENT_TREE_OBJECTID, extent_root);
515 if (ret) { 539 if (ret) {
516 mutex_unlock(&fs_info->fs_mutex); 540 mutex_unlock(&fs_info->fs_mutex);
@@ -611,11 +635,11 @@ int close_ctree(struct btrfs_root *root)
611 free_extent_buffer(fs_info->tree_root->node); 635 free_extent_buffer(fs_info->tree_root->node);
612 636
613 free_extent_buffer(fs_info->sb_buffer); 637 free_extent_buffer(fs_info->sb_buffer);
614 truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
615 iput(fs_info->btree_inode);
616 638
617 btrfs_free_block_groups(root->fs_info); 639 btrfs_free_block_groups(root->fs_info);
618 del_fs_roots(fs_info); 640 del_fs_roots(fs_info);
641 truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
642 iput(fs_info->btree_inode);
619 kfree(fs_info->extent_root); 643 kfree(fs_info->extent_root);
620 kfree(fs_info->tree_root); 644 kfree(fs_info->tree_root);
621 return 0; 645 return 0;
@@ -642,7 +666,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
642 666
643 if (transid != root->fs_info->generation) { 667 if (transid != root->fs_info->generation) {
644 printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", 668 printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n",
645 (unsigned long long)extent_buffer_blocknr(buf), 669 (unsigned long long)buf->start,
646 transid, root->fs_info->generation); 670 transid, root->fs_info->generation);
647 WARN_ON(1); 671 WARN_ON(1);
648 } 672 }