diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 91c2b27d9689..6137f06091e8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -751,7 +751,7 @@ again: | |||
751 | 751 | ||
752 | if (found_objectid != root_objectid) { | 752 | if (found_objectid != root_objectid) { |
753 | total_count = 2; | 753 | total_count = 2; |
754 | break; | 754 | goto out; |
755 | } | 755 | } |
756 | total_count = 1; | 756 | total_count = 1; |
757 | path->slots[0]++; | 757 | path->slots[0]++; |
@@ -760,8 +760,6 @@ again: | |||
760 | total_count = 0; | 760 | total_count = 0; |
761 | goto out; | 761 | goto out; |
762 | } | 762 | } |
763 | if (total_count > 1) | ||
764 | goto out; | ||
765 | if (level >= 0 && root->node == count_path->nodes[level]) | 763 | if (level >= 0 && root->node == count_path->nodes[level]) |
766 | goto out; | 764 | goto out; |
767 | level++; | 765 | level++; |
@@ -2109,22 +2107,23 @@ static int relocate_inode_pages(struct inode *inode, u64 start, u64 len) | |||
2109 | u64 delalloc_start; | 2107 | u64 delalloc_start; |
2110 | u64 existing_delalloc; | 2108 | u64 existing_delalloc; |
2111 | unsigned long last_index; | 2109 | unsigned long last_index; |
2112 | unsigned long first_index; | ||
2113 | unsigned long i; | 2110 | unsigned long i; |
2114 | struct page *page; | 2111 | struct page *page; |
2115 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2112 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2116 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 2113 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
2117 | struct file_ra_state ra; | 2114 | struct file_ra_state *ra; |
2115 | |||
2116 | ra = kzalloc(sizeof(*ra), GFP_NOFS); | ||
2118 | 2117 | ||
2119 | mutex_lock(&inode->i_mutex); | 2118 | mutex_lock(&inode->i_mutex); |
2120 | first_index = start >> PAGE_CACHE_SHIFT; | 2119 | i = start >> PAGE_CACHE_SHIFT; |
2121 | last_index = (start + len - 1) >> PAGE_CACHE_SHIFT; | 2120 | last_index = (start + len - 1) >> PAGE_CACHE_SHIFT; |
2122 | 2121 | ||
2123 | memset(&ra, 0, sizeof(ra)); | 2122 | file_ra_state_init(ra, inode->i_mapping); |
2124 | file_ra_state_init(&ra, inode->i_mapping); | 2123 | btrfs_force_ra(inode->i_mapping, ra, NULL, i, last_index); |
2125 | btrfs_force_ra(inode->i_mapping, &ra, NULL, first_index, last_index); | 2124 | kfree(ra); |
2126 | 2125 | ||
2127 | for (i = first_index; i <= last_index; i++) { | 2126 | for (; i <= last_index; i++) { |
2128 | page = grab_cache_page(inode->i_mapping, i); | 2127 | page = grab_cache_page(inode->i_mapping, i); |
2129 | if (!page) | 2128 | if (!page) |
2130 | goto out_unlock; | 2129 | goto out_unlock; |
@@ -2167,27 +2166,43 @@ out_unlock: | |||
2167 | return 0; | 2166 | return 0; |
2168 | } | 2167 | } |
2169 | 2168 | ||
2169 | /* | ||
2170 | * note, this releases the path | ||
2171 | */ | ||
2170 | static int relocate_one_reference(struct btrfs_root *extent_root, | 2172 | static int relocate_one_reference(struct btrfs_root *extent_root, |
2171 | struct btrfs_path *path, | 2173 | struct btrfs_path *path, |
2172 | struct btrfs_key *extent_key, | 2174 | struct btrfs_key *extent_key) |
2173 | u64 ref_root, u64 ref_gen, u64 ref_objectid, | ||
2174 | u64 ref_offset) | ||
2175 | { | 2175 | { |
2176 | struct inode *inode; | 2176 | struct inode *inode; |
2177 | struct btrfs_root *found_root; | 2177 | struct btrfs_root *found_root; |
2178 | struct btrfs_key root_location; | 2178 | struct btrfs_key *root_location; |
2179 | struct btrfs_extent_ref *ref; | ||
2180 | u64 ref_root; | ||
2181 | u64 ref_gen; | ||
2182 | u64 ref_objectid; | ||
2183 | u64 ref_offset; | ||
2179 | int ret; | 2184 | int ret; |
2180 | 2185 | ||
2181 | root_location.objectid = ref_root; | 2186 | ref = btrfs_item_ptr(path->nodes[0], path->slots[0], |
2187 | struct btrfs_extent_ref); | ||
2188 | ref_root = btrfs_ref_root(path->nodes[0], ref); | ||
2189 | ref_gen = btrfs_ref_generation(path->nodes[0], ref); | ||
2190 | ref_objectid = btrfs_ref_objectid(path->nodes[0], ref); | ||
2191 | ref_offset = btrfs_ref_offset(path->nodes[0], ref); | ||
2192 | btrfs_release_path(extent_root, path); | ||
2193 | |||
2194 | root_location = kmalloc(sizeof(*root_location), GFP_NOFS); | ||
2195 | root_location->objectid = ref_root; | ||
2182 | if (ref_gen == 0) | 2196 | if (ref_gen == 0) |
2183 | root_location.offset = 0; | 2197 | root_location->offset = 0; |
2184 | else | 2198 | else |
2185 | root_location.offset = (u64)-1; | 2199 | root_location->offset = (u64)-1; |
2186 | root_location.type = BTRFS_ROOT_ITEM_KEY; | 2200 | root_location->type = BTRFS_ROOT_ITEM_KEY; |
2187 | 2201 | ||
2188 | found_root = btrfs_read_fs_root_no_name(extent_root->fs_info, | 2202 | found_root = btrfs_read_fs_root_no_name(extent_root->fs_info, |
2189 | &root_location); | 2203 | root_location); |
2190 | BUG_ON(!found_root); | 2204 | BUG_ON(!found_root); |
2205 | kfree(root_location); | ||
2191 | 2206 | ||
2192 | if (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID) { | 2207 | if (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID) { |
2193 | mutex_unlock(&extent_root->fs_info->fs_mutex); | 2208 | mutex_unlock(&extent_root->fs_info->fs_mutex); |
@@ -2259,12 +2274,7 @@ static int relocate_one_extent(struct btrfs_root *extent_root, | |||
2259 | { | 2274 | { |
2260 | struct btrfs_key key; | 2275 | struct btrfs_key key; |
2261 | struct btrfs_key found_key; | 2276 | struct btrfs_key found_key; |
2262 | struct btrfs_extent_ref *ref; | ||
2263 | struct extent_buffer *leaf; | 2277 | struct extent_buffer *leaf; |
2264 | u64 ref_root; | ||
2265 | u64 ref_gen; | ||
2266 | u64 ref_objectid; | ||
2267 | u64 ref_offset; | ||
2268 | u32 nritems; | 2278 | u32 nritems; |
2269 | u32 item_size; | 2279 | u32 item_size; |
2270 | int ret = 0; | 2280 | int ret = 0; |
@@ -2297,17 +2307,7 @@ static int relocate_one_extent(struct btrfs_root *extent_root, | |||
2297 | key.offset = found_key.offset + 1; | 2307 | key.offset = found_key.offset + 1; |
2298 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); | 2308 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); |
2299 | 2309 | ||
2300 | ref = btrfs_item_ptr(leaf, path->slots[0], | 2310 | ret = relocate_one_reference(extent_root, path, extent_key); |
2301 | struct btrfs_extent_ref); | ||
2302 | ref_root = btrfs_ref_root(leaf, ref); | ||
2303 | ref_gen = btrfs_ref_generation(leaf, ref); | ||
2304 | ref_objectid = btrfs_ref_objectid(leaf, ref); | ||
2305 | ref_offset = btrfs_ref_offset(leaf, ref); | ||
2306 | btrfs_release_path(extent_root, path); | ||
2307 | |||
2308 | ret = relocate_one_reference(extent_root, path, | ||
2309 | extent_key, ref_root, ref_gen, | ||
2310 | ref_objectid, ref_offset); | ||
2311 | if (ret) | 2311 | if (ret) |
2312 | goto out; | 2312 | goto out; |
2313 | } | 2313 | } |
@@ -2354,7 +2354,6 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size) | |||
2354 | struct btrfs_path *path; | 2354 | struct btrfs_path *path; |
2355 | u64 cur_byte; | 2355 | u64 cur_byte; |
2356 | u64 total_found; | 2356 | u64 total_found; |
2357 | u64 ptr; | ||
2358 | struct btrfs_fs_info *info = root->fs_info; | 2357 | struct btrfs_fs_info *info = root->fs_info; |
2359 | struct extent_map_tree *block_group_cache; | 2358 | struct extent_map_tree *block_group_cache; |
2360 | struct btrfs_key key; | 2359 | struct btrfs_key key; |
@@ -2377,6 +2376,7 @@ again: | |||
2377 | key.offset = 0; | 2376 | key.offset = 0; |
2378 | key.type = 0; | 2377 | key.type = 0; |
2379 | while(1) { | 2378 | while(1) { |
2379 | |||
2380 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 2380 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
2381 | if (ret < 0) | 2381 | if (ret < 0) |
2382 | goto out; | 2382 | goto out; |
@@ -2441,6 +2441,8 @@ next: | |||
2441 | key.offset = 0; | 2441 | key.offset = 0; |
2442 | key.type = 0; | 2442 | key.type = 0; |
2443 | while(1) { | 2443 | while(1) { |
2444 | u64 ptr; | ||
2445 | |||
2444 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 2446 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
2445 | if (ret < 0) | 2447 | if (ret < 0) |
2446 | goto out; | 2448 | goto out; |