diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-15 16:15:53 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:56 -0400 |
commit | db94535db75e67fab12ccbb7f5ee548e33fed891 (patch) | |
tree | 1ad7dfc82b003294a94ee87d7329b24b902b369f /fs/btrfs/inode.c | |
parent | 1a5bc167f6707542b79a55452075525620ed43f5 (diff) |
Btrfs: Allow tree blocks larger than the page size
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 90 |
1 files changed, 44 insertions, 46 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fbe2836364e0..d6b3a55ed8e0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -77,19 +77,19 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | |||
77 | struct btrfs_trans_handle *trans; | 77 | struct btrfs_trans_handle *trans; |
78 | struct btrfs_key ins; | 78 | struct btrfs_key ins; |
79 | u64 alloc_hint = 0; | 79 | u64 alloc_hint = 0; |
80 | u64 num_blocks; | 80 | u64 num_bytes; |
81 | int ret; | 81 | int ret; |
82 | u64 blocksize = 1 << inode->i_blkbits; | 82 | u64 blocksize = root->sectorsize; |
83 | 83 | ||
84 | mutex_lock(&root->fs_info->fs_mutex); | 84 | mutex_lock(&root->fs_info->fs_mutex); |
85 | trans = btrfs_start_transaction(root, 1); | 85 | trans = btrfs_start_transaction(root, 1); |
86 | btrfs_set_trans_block_group(trans, inode); | 86 | btrfs_set_trans_block_group(trans, inode); |
87 | BUG_ON(!trans); | 87 | BUG_ON(!trans); |
88 | num_blocks = (end - start + blocksize) & ~(blocksize - 1); | 88 | num_bytes = (end - start + blocksize) & ~(blocksize - 1); |
89 | ret = btrfs_drop_extents(trans, root, inode, | 89 | ret = btrfs_drop_extents(trans, root, inode, |
90 | start, start + num_blocks, &alloc_hint); | 90 | start, start + num_bytes, &alloc_hint); |
91 | num_blocks = num_blocks >> inode->i_blkbits; | 91 | |
92 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_blocks, 0, | 92 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0, |
93 | alloc_hint, (u64)-1, &ins, 1); | 93 | alloc_hint, (u64)-1, &ins, 1); |
94 | if (ret) { | 94 | if (ret) { |
95 | WARN_ON(1); | 95 | WARN_ON(1); |
@@ -186,7 +186,8 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end) | |||
186 | zeroit: | 186 | zeroit: |
187 | printk("btrfs csum failed ino %lu off %llu\n", | 187 | printk("btrfs csum failed ino %lu off %llu\n", |
188 | page->mapping->host->i_ino, (unsigned long long)start); | 188 | page->mapping->host->i_ino, (unsigned long long)start); |
189 | memset(kaddr + offset, 1, end - start + 1); flush_dcache_page(page); | 189 | memset(kaddr + offset, 1, end - start + 1); |
190 | flush_dcache_page(page); | ||
190 | kunmap_atomic(kaddr, KM_IRQ0); | 191 | kunmap_atomic(kaddr, KM_IRQ0); |
191 | return 0; | 192 | return 0; |
192 | } | 193 | } |
@@ -547,7 +548,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
547 | struct extent_buffer *leaf; | 548 | struct extent_buffer *leaf; |
548 | struct btrfs_file_extent_item *fi; | 549 | struct btrfs_file_extent_item *fi; |
549 | u64 extent_start = 0; | 550 | u64 extent_start = 0; |
550 | u64 extent_num_blocks = 0; | 551 | u64 extent_num_bytes = 0; |
551 | u64 item_end = 0; | 552 | u64 item_end = 0; |
552 | int found_extent; | 553 | int found_extent; |
553 | int del_item; | 554 | int del_item; |
@@ -593,8 +594,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
593 | if (btrfs_file_extent_type(leaf, fi) != | 594 | if (btrfs_file_extent_type(leaf, fi) != |
594 | BTRFS_FILE_EXTENT_INLINE) { | 595 | BTRFS_FILE_EXTENT_INLINE) { |
595 | item_end += | 596 | item_end += |
596 | btrfs_file_extent_num_blocks(leaf, fi) << | 597 | btrfs_file_extent_num_bytes(leaf, fi); |
597 | inode->i_blkbits; | ||
598 | } | 598 | } |
599 | } | 599 | } |
600 | if (found_type == BTRFS_CSUM_ITEM_KEY) { | 600 | if (found_type == BTRFS_CSUM_ITEM_KEY) { |
@@ -626,28 +626,27 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
626 | btrfs_file_extent_type(leaf, fi) != | 626 | btrfs_file_extent_type(leaf, fi) != |
627 | BTRFS_FILE_EXTENT_INLINE) { | 627 | BTRFS_FILE_EXTENT_INLINE) { |
628 | u64 num_dec; | 628 | u64 num_dec; |
629 | extent_start = btrfs_file_extent_disk_blocknr(leaf, fi); | 629 | extent_start = btrfs_file_extent_disk_bytenr(leaf, fi); |
630 | if (!del_item) { | 630 | if (!del_item) { |
631 | u64 orig_num_blocks = | 631 | u64 orig_num_bytes = |
632 | btrfs_file_extent_num_blocks(leaf, fi); | 632 | btrfs_file_extent_num_bytes(leaf, fi); |
633 | extent_num_blocks = inode->i_size - | 633 | extent_num_bytes = inode->i_size - |
634 | found_key.offset + root->sectorsize - 1; | 634 | found_key.offset + root->sectorsize - 1; |
635 | extent_num_blocks >>= inode->i_blkbits; | 635 | btrfs_set_file_extent_num_bytes(leaf, fi, |
636 | btrfs_set_file_extent_num_blocks(leaf, fi, | 636 | extent_num_bytes); |
637 | extent_num_blocks); | 637 | num_dec = (orig_num_bytes - |
638 | num_dec = (orig_num_blocks - | 638 | extent_num_bytes) >> 9; |
639 | extent_num_blocks) << 3; | ||
640 | if (extent_start != 0) { | 639 | if (extent_start != 0) { |
641 | inode->i_blocks -= num_dec; | 640 | inode->i_blocks -= num_dec; |
642 | } | 641 | } |
643 | btrfs_mark_buffer_dirty(leaf); | 642 | btrfs_mark_buffer_dirty(leaf); |
644 | } else { | 643 | } else { |
645 | extent_num_blocks = | 644 | extent_num_bytes = |
646 | btrfs_file_extent_disk_num_blocks(leaf, | 645 | btrfs_file_extent_disk_num_bytes(leaf, |
647 | fi); | 646 | fi); |
648 | /* FIXME blocksize != 4096 */ | 647 | /* FIXME blocksize != 4096 */ |
649 | num_dec = btrfs_file_extent_num_blocks(leaf, | 648 | num_dec = btrfs_file_extent_num_bytes(leaf, |
650 | fi) << 3; | 649 | fi) >> 9; |
651 | if (extent_start != 0) { | 650 | if (extent_start != 0) { |
652 | found_extent = 1; | 651 | found_extent = 1; |
653 | inode->i_blocks -= num_dec; | 652 | inode->i_blocks -= num_dec; |
@@ -664,7 +663,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
664 | btrfs_release_path(root, path); | 663 | btrfs_release_path(root, path); |
665 | if (found_extent) { | 664 | if (found_extent) { |
666 | ret = btrfs_free_extent(trans, root, extent_start, | 665 | ret = btrfs_free_extent(trans, root, extent_start, |
667 | extent_num_blocks, 0); | 666 | extent_num_bytes, 0); |
668 | BUG_ON(ret); | 667 | BUG_ON(ret); |
669 | } | 668 | } |
670 | } | 669 | } |
@@ -709,7 +708,8 @@ static int btrfs_cow_one_page(struct inode *inode, struct page *page, | |||
709 | static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | 708 | static int btrfs_truncate_page(struct address_space *mapping, loff_t from) |
710 | { | 709 | { |
711 | struct inode *inode = mapping->host; | 710 | struct inode *inode = mapping->host; |
712 | unsigned blocksize = 1 << inode->i_blkbits; | 711 | struct btrfs_root *root = BTRFS_I(inode)->root; |
712 | u32 blocksize = root->sectorsize; | ||
713 | pgoff_t index = from >> PAGE_CACHE_SHIFT; | 713 | pgoff_t index = from >> PAGE_CACHE_SHIFT; |
714 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 714 | unsigned offset = from & (PAGE_CACHE_SIZE-1); |
715 | struct page *page; | 715 | struct page *page; |
@@ -719,7 +719,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | |||
719 | if ((offset & (blocksize - 1)) == 0) | 719 | if ((offset & (blocksize - 1)) == 0) |
720 | goto out; | 720 | goto out; |
721 | 721 | ||
722 | down_read(&BTRFS_I(inode)->root->snap_sem); | 722 | down_read(&root->snap_sem); |
723 | ret = -ENOMEM; | 723 | ret = -ENOMEM; |
724 | page = grab_cache_page(mapping, index); | 724 | page = grab_cache_page(mapping, index); |
725 | if (!page) | 725 | if (!page) |
@@ -778,8 +778,6 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
778 | err = btrfs_drop_extents(trans, root, inode, | 778 | err = btrfs_drop_extents(trans, root, inode, |
779 | pos, pos + hole_size, &alloc_hint); | 779 | pos, pos + hole_size, &alloc_hint); |
780 | 780 | ||
781 | hole_size >>= inode->i_blkbits; | ||
782 | |||
783 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, | 781 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, |
784 | pos, 0, 0, hole_size); | 782 | pos, 0, 0, hole_size); |
785 | btrfs_end_transaction(trans, root); | 783 | btrfs_end_transaction(trans, root); |
@@ -1490,7 +1488,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
1490 | { | 1488 | { |
1491 | int ret; | 1489 | int ret; |
1492 | int err = 0; | 1490 | int err = 0; |
1493 | u64 blocknr; | 1491 | u64 bytenr; |
1494 | u64 extent_start = 0; | 1492 | u64 extent_start = 0; |
1495 | u64 extent_end = 0; | 1493 | u64 extent_end = 0; |
1496 | u64 objectid = inode->i_ino; | 1494 | u64 objectid = inode->i_ino; |
@@ -1540,10 +1538,6 @@ again: | |||
1540 | leaf = path->nodes[0]; | 1538 | leaf = path->nodes[0]; |
1541 | item = btrfs_item_ptr(leaf, path->slots[0], | 1539 | item = btrfs_item_ptr(leaf, path->slots[0], |
1542 | struct btrfs_file_extent_item); | 1540 | struct btrfs_file_extent_item); |
1543 | |||
1544 | blocknr = btrfs_file_extent_disk_blocknr(leaf, item); | ||
1545 | blocknr += btrfs_file_extent_offset(leaf, item); | ||
1546 | |||
1547 | /* are we inside the extent that was found? */ | 1541 | /* are we inside the extent that was found? */ |
1548 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 1542 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
1549 | found_type = btrfs_key_type(&found_key); | 1543 | found_type = btrfs_key_type(&found_key); |
@@ -1556,8 +1550,7 @@ again: | |||
1556 | extent_start = found_key.offset; | 1550 | extent_start = found_key.offset; |
1557 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 1551 | if (found_type == BTRFS_FILE_EXTENT_REG) { |
1558 | extent_end = extent_start + | 1552 | extent_end = extent_start + |
1559 | (btrfs_file_extent_num_blocks(leaf, item) << | 1553 | btrfs_file_extent_num_bytes(leaf, item); |
1560 | inode->i_blkbits); | ||
1561 | err = 0; | 1554 | err = 0; |
1562 | if (start < extent_start || start >= extent_end) { | 1555 | if (start < extent_start || start >= extent_end) { |
1563 | em->start = start; | 1556 | em->start = start; |
@@ -1570,17 +1563,18 @@ again: | |||
1570 | } | 1563 | } |
1571 | goto not_found_em; | 1564 | goto not_found_em; |
1572 | } | 1565 | } |
1573 | if (btrfs_file_extent_disk_blocknr(leaf, item) == 0) { | 1566 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); |
1567 | if (bytenr == 0) { | ||
1574 | em->start = extent_start; | 1568 | em->start = extent_start; |
1575 | em->end = extent_end - 1; | 1569 | em->end = extent_end - 1; |
1576 | em->block_start = EXTENT_MAP_HOLE; | 1570 | em->block_start = EXTENT_MAP_HOLE; |
1577 | em->block_end = EXTENT_MAP_HOLE; | 1571 | em->block_end = EXTENT_MAP_HOLE; |
1578 | goto insert; | 1572 | goto insert; |
1579 | } | 1573 | } |
1580 | em->block_start = blocknr << inode->i_blkbits; | 1574 | bytenr += btrfs_file_extent_offset(leaf, item); |
1575 | em->block_start = bytenr; | ||
1581 | em->block_end = em->block_start + | 1576 | em->block_end = em->block_start + |
1582 | (btrfs_file_extent_num_blocks(leaf, item) << | 1577 | btrfs_file_extent_num_bytes(leaf, item) - 1; |
1583 | inode->i_blkbits) - 1; | ||
1584 | em->start = extent_start; | 1578 | em->start = extent_start; |
1585 | em->end = extent_end - 1; | 1579 | em->end = extent_end - 1; |
1586 | goto insert; | 1580 | goto insert; |
@@ -1592,7 +1586,8 @@ again: | |||
1592 | size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf, | 1586 | size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf, |
1593 | path->slots[0])); | 1587 | path->slots[0])); |
1594 | 1588 | ||
1595 | extent_end = extent_start | ((u64)root->sectorsize - 1); | 1589 | extent_end = (extent_start + size) | |
1590 | ((u64)root->sectorsize - 1); | ||
1596 | if (start < extent_start || start >= extent_end) { | 1591 | if (start < extent_start || start >= extent_end) { |
1597 | em->start = start; | 1592 | em->start = start; |
1598 | if (start < extent_start) { | 1593 | if (start < extent_start) { |
@@ -1617,8 +1612,10 @@ again: | |||
1617 | ptr = btrfs_file_extent_inline_start(item); | 1612 | ptr = btrfs_file_extent_inline_start(item); |
1618 | map = kmap(page); | 1613 | map = kmap(page); |
1619 | read_extent_buffer(leaf, map + page_offset, ptr, size); | 1614 | read_extent_buffer(leaf, map + page_offset, ptr, size); |
1615 | /* | ||
1620 | memset(map + page_offset + size, 0, | 1616 | memset(map + page_offset + size, 0, |
1621 | root->sectorsize - (page_offset + size)); | 1617 | root->sectorsize - (page_offset + size)); |
1618 | */ | ||
1622 | flush_dcache_page(page); | 1619 | flush_dcache_page(page); |
1623 | kunmap(page); | 1620 | kunmap(page); |
1624 | set_extent_uptodate(em_tree, extent_start, | 1621 | set_extent_uptodate(em_tree, extent_start, |
@@ -1836,13 +1833,13 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
1836 | trans = btrfs_start_transaction(root, 1); | 1833 | trans = btrfs_start_transaction(root, 1); |
1837 | BUG_ON(!trans); | 1834 | BUG_ON(!trans); |
1838 | 1835 | ||
1839 | leaf = btrfs_alloc_free_block(trans, root, 0, 0); | 1836 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0, 0); |
1840 | if (IS_ERR(leaf)) | 1837 | if (IS_ERR(leaf)) |
1841 | return PTR_ERR(leaf); | 1838 | return PTR_ERR(leaf); |
1842 | 1839 | ||
1843 | btrfs_set_header_nritems(leaf, 0); | 1840 | btrfs_set_header_nritems(leaf, 0); |
1844 | btrfs_set_header_level(leaf, 0); | 1841 | btrfs_set_header_level(leaf, 0); |
1845 | btrfs_set_header_blocknr(leaf, extent_buffer_blocknr(leaf)); | 1842 | btrfs_set_header_bytenr(leaf, leaf->start); |
1846 | btrfs_set_header_generation(leaf, trans->transid); | 1843 | btrfs_set_header_generation(leaf, trans->transid); |
1847 | btrfs_set_header_owner(leaf, root->root_key.objectid); | 1844 | btrfs_set_header_owner(leaf, root->root_key.objectid); |
1848 | write_extent_buffer(leaf, root->fs_info->fsid, | 1845 | write_extent_buffer(leaf, root->fs_info->fsid, |
@@ -1858,7 +1855,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
1858 | inode_item->nblocks = cpu_to_le64(1); | 1855 | inode_item->nblocks = cpu_to_le64(1); |
1859 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); | 1856 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); |
1860 | 1857 | ||
1861 | btrfs_set_root_blocknr(&root_item, extent_buffer_blocknr(leaf)); | 1858 | btrfs_set_root_bytenr(&root_item, leaf->start); |
1859 | btrfs_set_root_level(&root_item, 0); | ||
1862 | btrfs_set_root_refs(&root_item, 1); | 1860 | btrfs_set_root_refs(&root_item, 1); |
1863 | btrfs_set_root_used(&root_item, 0); | 1861 | btrfs_set_root_used(&root_item, 0); |
1864 | 1862 | ||
@@ -1971,8 +1969,8 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
1971 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 1969 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
1972 | 1970 | ||
1973 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | 1971 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); |
1974 | btrfs_set_root_blocknr(&new_root_item, | 1972 | btrfs_set_root_bytenr(&new_root_item, root->node->start); |
1975 | extent_buffer_blocknr(root->node)); | 1973 | btrfs_set_root_level(&new_root_item, btrfs_header_level(root->node)); |
1976 | 1974 | ||
1977 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 1975 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
1978 | &new_root_item); | 1976 | &new_root_item); |