diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 32 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 15 |
2 files changed, 36 insertions, 11 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 660b05a4baf5..99a8b0f0d318 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -192,11 +192,13 @@ static u64 noinline find_search_start(struct btrfs_root *root, | |||
192 | u64 start = 0; | 192 | u64 start = 0; |
193 | u64 end = 0; | 193 | u64 end = 0; |
194 | u64 cache_miss = 0; | 194 | u64 cache_miss = 0; |
195 | u64 total_fs_bytes; | ||
195 | int wrapped = 0; | 196 | int wrapped = 0; |
196 | 197 | ||
197 | if (!cache) { | 198 | if (!cache) { |
198 | goto out; | 199 | goto out; |
199 | } | 200 | } |
201 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
200 | again: | 202 | again: |
201 | ret = cache_block_group(root, cache); | 203 | ret = cache_block_group(root, cache); |
202 | if (ret) | 204 | if (ret) |
@@ -223,6 +225,8 @@ again: | |||
223 | if (data != BTRFS_BLOCK_GROUP_MIXED && | 225 | if (data != BTRFS_BLOCK_GROUP_MIXED && |
224 | start + num > cache->key.objectid + cache->key.offset) | 226 | start + num > cache->key.objectid + cache->key.offset) |
225 | goto new_group; | 227 | goto new_group; |
228 | if (start + num > total_fs_bytes) | ||
229 | goto new_group; | ||
226 | return start; | 230 | return start; |
227 | } | 231 | } |
228 | out: | 232 | out: |
@@ -239,7 +243,7 @@ new_group: | |||
239 | last = cache->key.objectid + cache->key.offset; | 243 | last = cache->key.objectid + cache->key.offset; |
240 | wrapped: | 244 | wrapped: |
241 | cache = btrfs_lookup_block_group(root->fs_info, last); | 245 | cache = btrfs_lookup_block_group(root->fs_info, last); |
242 | if (!cache) { | 246 | if (!cache || cache->key.objectid >= total_fs_bytes) { |
243 | no_cache: | 247 | no_cache: |
244 | if (!wrapped) { | 248 | if (!wrapped) { |
245 | wrapped = 1; | 249 | wrapped = 1; |
@@ -287,6 +291,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
287 | u64 end; | 291 | u64 end; |
288 | u64 free_check; | 292 | u64 free_check; |
289 | u64 ptr; | 293 | u64 ptr; |
294 | u64 total_fs_bytes; | ||
290 | int bit; | 295 | int bit; |
291 | int ret; | 296 | int ret; |
292 | int full_search = 0; | 297 | int full_search = 0; |
@@ -294,6 +299,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
294 | int data_swap = 0; | 299 | int data_swap = 0; |
295 | 300 | ||
296 | block_group_cache = &info->block_group_cache; | 301 | block_group_cache = &info->block_group_cache; |
302 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
297 | 303 | ||
298 | if (!owner) | 304 | if (!owner) |
299 | factor = 8; | 305 | factor = 8; |
@@ -306,7 +312,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
306 | else | 312 | else |
307 | bit = BLOCK_GROUP_METADATA; | 313 | bit = BLOCK_GROUP_METADATA; |
308 | 314 | ||
309 | if (search_start) { | 315 | if (search_start && search_start < total_fs_bytes) { |
310 | struct btrfs_block_group_cache *shint; | 316 | struct btrfs_block_group_cache *shint; |
311 | shint = btrfs_lookup_block_group(info, search_start); | 317 | shint = btrfs_lookup_block_group(info, search_start); |
312 | if (shint && (shint->data == data || | 318 | if (shint && (shint->data == data || |
@@ -318,8 +324,8 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
318 | } | 324 | } |
319 | } | 325 | } |
320 | } | 326 | } |
321 | if (hint && (hint->data == data || | 327 | if (hint && hint->key.objectid < total_fs_bytes && |
322 | hint->data == BTRFS_BLOCK_GROUP_MIXED)) { | 328 | (hint->data == data || hint->data == BTRFS_BLOCK_GROUP_MIXED)) { |
323 | used = btrfs_block_group_used(&hint->item); | 329 | used = btrfs_block_group_used(&hint->item); |
324 | if (used + hint->pinned < | 330 | if (used + hint->pinned < |
325 | div_factor(hint->key.offset, factor)) { | 331 | div_factor(hint->key.offset, factor)) { |
@@ -333,6 +339,8 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
333 | else | 339 | else |
334 | hint_last = search_start; | 340 | hint_last = search_start; |
335 | 341 | ||
342 | if (hint_last >= total_fs_bytes) | ||
343 | hint_last = search_start; | ||
336 | last = hint_last; | 344 | last = hint_last; |
337 | } | 345 | } |
338 | again: | 346 | again: |
@@ -350,6 +358,9 @@ again: | |||
350 | last = cache->key.objectid + cache->key.offset; | 358 | last = cache->key.objectid + cache->key.offset; |
351 | used = btrfs_block_group_used(&cache->item); | 359 | used = btrfs_block_group_used(&cache->item); |
352 | 360 | ||
361 | if (cache->key.objectid > total_fs_bytes) | ||
362 | break; | ||
363 | |||
353 | if (full_search) | 364 | if (full_search) |
354 | free_check = cache->key.offset; | 365 | free_check = cache->key.offset; |
355 | else | 366 | else |
@@ -1420,8 +1431,8 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1420 | data = BTRFS_BLOCK_GROUP_MIXED; | 1431 | data = BTRFS_BLOCK_GROUP_MIXED; |
1421 | } | 1432 | } |
1422 | 1433 | ||
1423 | if (search_end == (u64)-1) | 1434 | search_end = min(search_end, |
1424 | search_end = btrfs_super_total_bytes(&info->super_copy); | 1435 | btrfs_super_total_bytes(&info->super_copy)); |
1425 | if (hint_byte) { | 1436 | if (hint_byte) { |
1426 | block_group = btrfs_lookup_block_group(info, hint_byte); | 1437 | block_group = btrfs_lookup_block_group(info, hint_byte); |
1427 | if (!block_group) | 1438 | if (!block_group) |
@@ -1617,7 +1628,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1617 | { | 1628 | { |
1618 | int ret; | 1629 | int ret; |
1619 | int pending_ret; | 1630 | int pending_ret; |
1620 | u64 super_used, root_used; | 1631 | u64 super_used; |
1632 | u64 root_used; | ||
1621 | u64 search_start = 0; | 1633 | u64 search_start = 0; |
1622 | u64 new_hint; | 1634 | u64 new_hint; |
1623 | struct btrfs_fs_info *info = root->fs_info; | 1635 | struct btrfs_fs_info *info = root->fs_info; |
@@ -1636,6 +1648,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1636 | search_start, search_end, hint_byte, ins, | 1648 | search_start, search_end, hint_byte, ins, |
1637 | trans->alloc_exclude_start, | 1649 | trans->alloc_exclude_start, |
1638 | trans->alloc_exclude_nr, data); | 1650 | trans->alloc_exclude_nr, data); |
1651 | if (ret) | ||
1652 | printk("find free extent returns %d\n", ret); | ||
1639 | BUG_ON(ret); | 1653 | BUG_ON(ret); |
1640 | if (ret) | 1654 | if (ret) |
1641 | return ret; | 1655 | return ret; |
@@ -2292,8 +2306,6 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, | |||
2292 | while(1) { | 2306 | while(1) { |
2293 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); | 2307 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); |
2294 | 2308 | ||
2295 | BUG_ON(ret == 0); | ||
2296 | |||
2297 | if (ret < 0) | 2309 | if (ret < 0) |
2298 | goto out; | 2310 | goto out; |
2299 | 2311 | ||
@@ -2340,6 +2352,8 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size) | |||
2340 | int progress = 0; | 2352 | int progress = 0; |
2341 | 2353 | ||
2342 | btrfs_set_super_total_bytes(&info->super_copy, new_size); | 2354 | btrfs_set_super_total_bytes(&info->super_copy, new_size); |
2355 | clear_extent_dirty(&info->free_space_cache, new_size, (u64)-1, | ||
2356 | GFP_NOFS); | ||
2343 | block_group_cache = &info->block_group_cache; | 2357 | block_group_cache = &info->block_group_cache; |
2344 | path = btrfs_alloc_path(); | 2358 | path = btrfs_alloc_path(); |
2345 | root = root->fs_info->extent_root; | 2359 | root = root->fs_info->extent_root; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2cb2dd32407e..281757007ddb 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -148,6 +148,7 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) | |||
148 | u64 bytenr; | 148 | u64 bytenr; |
149 | u64 cow_end; | 149 | u64 cow_end; |
150 | u64 loops = 0; | 150 | u64 loops = 0; |
151 | u64 total_fs_bytes; | ||
151 | struct btrfs_root *root = BTRFS_I(inode)->root; | 152 | struct btrfs_root *root = BTRFS_I(inode)->root; |
152 | struct extent_buffer *leaf; | 153 | struct extent_buffer *leaf; |
153 | int found_type; | 154 | int found_type; |
@@ -157,6 +158,7 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) | |||
157 | int err; | 158 | int err; |
158 | struct btrfs_key found_key; | 159 | struct btrfs_key found_key; |
159 | 160 | ||
161 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
160 | path = btrfs_alloc_path(); | 162 | path = btrfs_alloc_path(); |
161 | BUG_ON(!path); | 163 | BUG_ON(!path); |
162 | again: | 164 | again: |
@@ -189,8 +191,10 @@ again: | |||
189 | found_type = btrfs_file_extent_type(leaf, item); | 191 | found_type = btrfs_file_extent_type(leaf, item); |
190 | extent_start = found_key.offset; | 192 | extent_start = found_key.offset; |
191 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 193 | if (found_type == BTRFS_FILE_EXTENT_REG) { |
192 | extent_end = extent_start + | 194 | u64 extent_num_bytes; |
193 | btrfs_file_extent_num_bytes(leaf, item); | 195 | |
196 | extent_num_bytes = btrfs_file_extent_num_bytes(leaf, item); | ||
197 | extent_end = extent_start + extent_num_bytes; | ||
194 | err = 0; | 198 | err = 0; |
195 | 199 | ||
196 | if (loops && start != extent_start) | 200 | if (loops && start != extent_start) |
@@ -204,6 +208,13 @@ again: | |||
204 | if (bytenr == 0) | 208 | if (bytenr == 0) |
205 | goto not_found; | 209 | goto not_found; |
206 | 210 | ||
211 | /* | ||
212 | * we may be called by the resizer, make sure we're inside | ||
213 | * the limits of the FS | ||
214 | */ | ||
215 | if (bytenr + extent_num_bytes > total_fs_bytes) | ||
216 | goto not_found; | ||
217 | |||
207 | if (btrfs_count_snapshots_in_path(root, path, bytenr) != 1) { | 218 | if (btrfs_count_snapshots_in_path(root, path, bytenr) != 1) { |
208 | goto not_found; | 219 | goto not_found; |
209 | } | 220 | } |