diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-29 09:59:12 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | 70dec8079d78691e476cc6c7cede40656078ad30 (patch) | |
tree | 19ab80f247fc026c3f5a5713381e98372737227b /fs/btrfs/inode.c | |
parent | aadfeb6e39ad6bde080cb3ab23f4da57ccb25f4a (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.c | 35 |
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 | ||
334 | int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end) | 334 | int 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 | ||
1832 | struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | 1838 | struct 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 | ||
2080 | static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags) | 2091 | static 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); |