Yan Zheng
2007-Oct-28 17:21 UTC
[Btrfs-devel][PATCH]Fix inline extent handling in btrfs_get_extent
Hello, This patch contain following fix: 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) Regards YZ --- diff -r a1bde8e797ff inode.c --- a/inode.c Thu Oct 25 15:49:25 2007 -0400 +++ b/inode.c Sun Oct 28 21:32:02 2007 +0800 @@ -1597,7 +1597,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; @@ -1611,28 +1611,34 @@ again: goto not_found_em; } - extent_offset = (page->index << PAGE_CACHE_SHIFT) - - extent_start; - ptr = btrfs_file_extent_inline_start(item) + extent_offset; - map = kmap(page); + 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 + 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); - /* - memset(map + page_offset + copy_size, 0, - PAGE_CACHE_SIZE - copy_size - page_offset); - */ + + 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); + } + flush_dcache_page(page); kunmap(page); set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS);