summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorYan2007-10-29 16:41:07 +0100
committerChris Mason2008-09-25 17:03:57 +0200
commit689f9346612d96ab93890160cf2fe0df5217ab73 (patch)
tree6a5e153e2cadf1042e28eab79956cad849056064 /fs/btrfs/inode.c
parentBtrfs: Fix extent_map leak in extent_bmap (diff)
downloadkernel-qcow2-linux-689f9346612d96ab93890160cf2fe0df5217ab73.tar.gz
kernel-qcow2-linux-689f9346612d96ab93890160cf2fe0df5217ab73.tar.xz
kernel-qcow2-linux-689f9346612d96ab93890160cf2fe0df5217ab73.zip
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.c34
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:
size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf,
path->slots[0]));
-
- extent_end = (extent_start + size) |
+ extent_end = (extent_start + size - 1) |
((u64)root->sectorsize - 1);
if (start < extent_start || start >= extent_end) {
em->start = start;
@@ -1610,29 +1609,32 @@ again:
}
goto not_found_em;
}
+ em->block_start = EXTENT_MAP_INLINE;
+ em->block_end = EXTENT_MAP_INLINE;
+
+ if (!page) {
+ em->start = extent_start;
+ em->end = extent_start + size - 1;
+ goto out;
+ }
extent_offset = (page->index << PAGE_CACHE_SHIFT) -
- extent_start;
- ptr = btrfs_file_extent_inline_start(item) + extent_offset;
- map = kmap(page);
+ extent_start + page_offset;
copy_size = min_t(u64, PAGE_CACHE_SIZE - page_offset,
size - extent_offset);
-
- em->block_start = EXTENT_MAP_INLINE;
- em->block_end = EXTENT_MAP_INLINE;
em->start = extent_start + extent_offset;
em->end = (em->start + copy_size -1) |
((u64)root->sectorsize -1);
-
- if (!page) {
- goto insert;
+ map = kmap(page);
+ ptr = btrfs_file_extent_inline_start(item) + extent_offset;
+ read_extent_buffer(leaf, map + page_offset, ptr, copy_size);
+
+ if (em->start + copy_size <= em->end) {
+ size = min_t(u64, em->end + 1 - em->start,
+ PAGE_CACHE_SIZE - page_offset) - copy_size;
+ memset(map + page_offset + copy_size, 0, size);
}
- read_extent_buffer(leaf, map + page_offset, ptr, copy_size);
- /*
- memset(map + page_offset + copy_size, 0,
- PAGE_CACHE_SIZE - copy_size - page_offset);
- */
flush_dcache_page(page);
kunmap(page);
set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS);