aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-01-29 09:59:12 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:59 -0400
commit70dec8079d78691e476cc6c7cede40656078ad30 (patch)
tree19ab80f247fc026c3f5a5713381e98372737227b /fs/btrfs/inode.c
parentaadfeb6e39ad6bde080cb3ab23f4da57ccb25f4a (diff)
Btrfs: extent_io and extent_state optimizations
The end_bio routines are changed to take a pointer to the extent state struct, and the state tree is walked in order to set/clear appropriate bits as IO completes. This greatly reduces the number of rbtree searches done by the end_bio handlers, and reduces lock contention. The extent_io releasepage function is changed to avoid expensive searches for locked state. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 484551274100..bac8722e14e1 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -331,7 +331,8 @@ out:
331 return ret; 331 return ret;
332} 332}
333 333
334int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end) 334int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
335 struct extent_state *state)
335{ 336{
336 size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT); 337 size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT);
337 struct inode *inode = page->mapping->host; 338 struct inode *inode = page->mapping->host;
@@ -347,7 +348,12 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end)
347 btrfs_test_flag(inode, NODATASUM)) 348 btrfs_test_flag(inode, NODATASUM))
348 return 0; 349 return 0;
349 350
350 ret = get_state_private(io_tree, start, &private); 351 if (state->start == start) {
352 private = state->private;
353 ret = 0;
354 } else {
355 ret = get_state_private(io_tree, start, &private);
356 }
351 local_irq_save(flags); 357 local_irq_save(flags);
352 kaddr = kmap_atomic(page, KM_IRQ0); 358 kaddr = kmap_atomic(page, KM_IRQ0);
353 if (ret) { 359 if (ret) {
@@ -1830,7 +1836,7 @@ out_unlock:
1830} 1836}
1831 1837
1832struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, 1838struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
1833 size_t page_offset, u64 start, u64 len, 1839 size_t pg_offset, u64 start, u64 len,
1834 int create) 1840 int create)
1835{ 1841{
1836 int ret; 1842 int ret;
@@ -1865,7 +1871,10 @@ again:
1865 start, len, em->start, em->len); 1871 start, len, em->start, em->len);
1866 WARN_ON(1); 1872 WARN_ON(1);
1867 } 1873 }
1868 goto out; 1874 if (em->block_start == EXTENT_MAP_INLINE && page)
1875 free_extent_map(em);
1876 else
1877 goto out;
1869 } 1878 }
1870 em = alloc_extent_map(GFP_NOFS); 1879 em = alloc_extent_map(GFP_NOFS);
1871 if (!em) { 1880 if (!em) {
@@ -1930,6 +1939,7 @@ again:
1930 em->len = extent_end - extent_start; 1939 em->len = extent_end - extent_start;
1931 goto insert; 1940 goto insert;
1932 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { 1941 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
1942 u64 page_start;
1933 unsigned long ptr; 1943 unsigned long ptr;
1934 char *map; 1944 char *map;
1935 size_t size; 1945 size_t size;
@@ -1959,16 +1969,17 @@ again:
1959 goto out; 1969 goto out;
1960 } 1970 }
1961 1971
1962 extent_offset = ((u64)page->index << PAGE_CACHE_SHIFT) - 1972 page_start = page_offset(page) + pg_offset;
1963 extent_start + page_offset; 1973 extent_offset = page_start - extent_start;
1964 copy_size = min_t(u64, PAGE_CACHE_SIZE - page_offset, 1974 copy_size = min_t(u64, PAGE_CACHE_SIZE - pg_offset,
1965 size - extent_offset); 1975 size - extent_offset);
1966 em->start = extent_start + extent_offset; 1976 em->start = extent_start + extent_offset;
1967 em->len = copy_size; 1977 em->len = (copy_size + root->sectorsize - 1) &
1978 ~((u64)root->sectorsize - 1);
1968 map = kmap(page); 1979 map = kmap(page);
1969 ptr = btrfs_file_extent_inline_start(item) + extent_offset; 1980 ptr = btrfs_file_extent_inline_start(item) + extent_offset;
1970 if (create == 0 && !PageUptodate(page)) { 1981 if (create == 0 && !PageUptodate(page)) {
1971 read_extent_buffer(leaf, map + page_offset, ptr, 1982 read_extent_buffer(leaf, map + pg_offset, ptr,
1972 copy_size); 1983 copy_size);
1973 flush_dcache_page(page); 1984 flush_dcache_page(page);
1974 } else if (create && PageUptodate(page)) { 1985 } else if (create && PageUptodate(page)) {
@@ -1980,7 +1991,7 @@ again:
1980 trans = btrfs_start_transaction(root, 1); 1991 trans = btrfs_start_transaction(root, 1);
1981 goto again; 1992 goto again;
1982 } 1993 }
1983 write_extent_buffer(leaf, map + page_offset, ptr, 1994 write_extent_buffer(leaf, map + pg_offset, ptr,
1984 copy_size); 1995 copy_size);
1985 btrfs_mark_buffer_dirty(leaf); 1996 btrfs_mark_buffer_dirty(leaf);
1986 } 1997 }
@@ -2077,7 +2088,7 @@ btrfs_readpages(struct file *file, struct address_space *mapping,
2077 btrfs_get_extent); 2088 btrfs_get_extent);
2078} 2089}
2079 2090
2080static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags) 2091static int btrfs_releasepage(struct page *page, gfp_t gfp_flags)
2081{ 2092{
2082 struct extent_io_tree *tree; 2093 struct extent_io_tree *tree;
2083 struct extent_map_tree *map; 2094 struct extent_map_tree *map;
@@ -2085,7 +2096,7 @@ static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
2085 2096
2086 tree = &BTRFS_I(page->mapping->host)->io_tree; 2097 tree = &BTRFS_I(page->mapping->host)->io_tree;
2087 map = &BTRFS_I(page->mapping->host)->extent_tree; 2098 map = &BTRFS_I(page->mapping->host)->extent_tree;
2088 ret = try_release_extent_mapping(map, tree, page); 2099 ret = try_release_extent_mapping(map, tree, page, gfp_flags);
2089 if (ret == 1) { 2100 if (ret == 1) {
2090 ClearPagePrivate(page); 2101 ClearPagePrivate(page);
2091 set_page_private(page, 0); 2102 set_page_private(page, 0);