aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-01-08 15:46:31 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:59 -0400
commitc31f8830f0dfd31e7e196b85ca1b39aef8b77d57 (patch)
tree2ee8038af3d28460dd9004ab69d48d301c0a76b8 /fs/btrfs/extent-tree.c
parentb0331a4c4c339ba7786472b137d6ece9e7f810ec (diff)
Btrfs: online shrinking fixes
While shrinking the FS, the allocation functions need to make sure they don't try to allocate bytes past the end of the FS. nodatacow needed an extra check to force cows when the existing extents are past the end of the FS. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c32
1 files changed, 23 insertions, 9 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);
200again: 202again:
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 }
228out: 232out:
@@ -239,7 +243,7 @@ new_group:
239 last = cache->key.objectid + cache->key.offset; 243 last = cache->key.objectid + cache->key.offset;
240wrapped: 244wrapped:
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) {
243no_cache: 247no_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 }
338again: 346again:
@@ -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);
1651if (ret)
1652printk("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;