diff options
author | Yan <yanzheng@21cn.com> | 2007-10-29 11:41:07 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:57 -0400 |
commit | 689f9346612d96ab93890160cf2fe0df5217ab73 (patch) | |
tree | 6a5e153e2cadf1042e28eab79956cad849056064 /fs/btrfs/inode.c | |
parent | c67cda1758130f3e437744c4c2ec4a7cc25564e3 (diff) |
Fix inline extent handling in btrfs_get_extent
1. Reorder kmap and the test for 'page != NULL'
2. Zero-fill rest area of a block when inline extent isn't big enough.
3. Do not insert extent_map into the map tree when page == NULL.
(If insert the extent_map into the map tree, subsequent read requests
will find it in the map tree directly and the corresponding inline
extent data aren't copied into page by the the get_extent function.
extent_read_full_page can't handle that case)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c88f13a88555..0ba1cdbdf112 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1596,8 +1596,7 @@ again: | |||
1596 | 1596 | ||
1597 | size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf, | 1597 | size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf, |
1598 | path->slots[0])); | 1598 | path->slots[0])); |
1599 | 1599 | extent_end = (extent_start + size - 1) | | |
1600 | extent_end = (extent_start + size) | | ||
1601 | ((u64)root->sectorsize - 1); | 1600 | ((u64)root->sectorsize - 1); |
1602 | if (start < extent_start || start >= extent_end) { | 1601 | if (start < extent_start || start >= extent_end) { |
1603 | em->start = start; | 1602 | em->start = start; |
@@ -1610,29 +1609,32 @@ again: | |||
1610 | } | 1609 | } |
1611 | goto not_found_em; | 1610 | goto not_found_em; |
1612 | } | 1611 | } |
1612 | em->block_start = EXTENT_MAP_INLINE; | ||
1613 | em->block_end = EXTENT_MAP_INLINE; | ||
1614 | |||
1615 | if (!page) { | ||
1616 | em->start = extent_start; | ||
1617 | em->end = extent_start + size - 1; | ||
1618 | goto out; | ||
1619 | } | ||
1613 | 1620 | ||
1614 | extent_offset = (page->index << PAGE_CACHE_SHIFT) - | 1621 | extent_offset = (page->index << PAGE_CACHE_SHIFT) - |
1615 | extent_start; | 1622 | extent_start + page_offset; |
1616 | ptr = btrfs_file_extent_inline_start(item) + extent_offset; | ||
1617 | map = kmap(page); | ||
1618 | copy_size = min_t(u64, PAGE_CACHE_SIZE - page_offset, | 1623 | copy_size = min_t(u64, PAGE_CACHE_SIZE - page_offset, |
1619 | size - extent_offset); | 1624 | size - extent_offset); |
1620 | |||
1621 | em->block_start = EXTENT_MAP_INLINE; | ||
1622 | em->block_end = EXTENT_MAP_INLINE; | ||
1623 | em->start = extent_start + extent_offset; | 1625 | em->start = extent_start + extent_offset; |
1624 | em->end = (em->start + copy_size -1) | | 1626 | em->end = (em->start + copy_size -1) | |
1625 | ((u64)root->sectorsize -1); | 1627 | ((u64)root->sectorsize -1); |
1626 | 1628 | map = kmap(page); | |
1627 | if (!page) { | 1629 | ptr = btrfs_file_extent_inline_start(item) + extent_offset; |
1628 | goto insert; | 1630 | read_extent_buffer(leaf, map + page_offset, ptr, copy_size); |
1631 | |||
1632 | if (em->start + copy_size <= em->end) { | ||
1633 | size = min_t(u64, em->end + 1 - em->start, | ||
1634 | PAGE_CACHE_SIZE - page_offset) - copy_size; | ||
1635 | memset(map + page_offset + copy_size, 0, size); | ||
1629 | } | 1636 | } |
1630 | 1637 | ||
1631 | read_extent_buffer(leaf, map + page_offset, ptr, copy_size); | ||
1632 | /* | ||
1633 | memset(map + page_offset + copy_size, 0, | ||
1634 | PAGE_CACHE_SIZE - copy_size - page_offset); | ||
1635 | */ | ||
1636 | flush_dcache_page(page); | 1638 | flush_dcache_page(page); |
1637 | kunmap(page); | 1639 | kunmap(page); |
1638 | set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS); | 1640 | set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS); |