diff options
| -rw-r--r-- | fs/btrfs/extent-tree.c | 21 | ||||
| -rw-r--r-- | fs/btrfs/free-space-cache.c | 73 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/relocation.c | 9 | ||||
| -rw-r--r-- | fs/btrfs/zlib.c | 6 |
5 files changed, 92 insertions, 20 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index dc84daee6bc4..72a2b9c28e9f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -265,10 +265,6 @@ static int caching_kthread(void *data) | |||
| 265 | 265 | ||
| 266 | atomic_inc(&block_group->space_info->caching_threads); | 266 | atomic_inc(&block_group->space_info->caching_threads); |
| 267 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); | 267 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); |
| 268 | again: | ||
| 269 | /* need to make sure the commit_root doesn't disappear */ | ||
| 270 | down_read(&fs_info->extent_commit_sem); | ||
| 271 | |||
| 272 | /* | 268 | /* |
| 273 | * We don't want to deadlock with somebody trying to allocate a new | 269 | * We don't want to deadlock with somebody trying to allocate a new |
| 274 | * extent for the extent root while also trying to search the extent | 270 | * extent for the extent root while also trying to search the extent |
| @@ -282,6 +278,10 @@ again: | |||
| 282 | key.objectid = last; | 278 | key.objectid = last; |
| 283 | key.offset = 0; | 279 | key.offset = 0; |
| 284 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 280 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 281 | again: | ||
| 282 | /* need to make sure the commit_root doesn't disappear */ | ||
| 283 | down_read(&fs_info->extent_commit_sem); | ||
| 284 | |||
| 285 | ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); | 285 | ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); |
| 286 | if (ret < 0) | 286 | if (ret < 0) |
| 287 | goto err; | 287 | goto err; |
| @@ -304,6 +304,19 @@ again: | |||
| 304 | 304 | ||
| 305 | if (need_resched() || | 305 | if (need_resched() || |
| 306 | btrfs_transaction_in_commit(fs_info)) { | 306 | btrfs_transaction_in_commit(fs_info)) { |
| 307 | leaf = path->nodes[0]; | ||
| 308 | |||
| 309 | /* this shouldn't happen, but if the | ||
| 310 | * leaf is empty just move on. | ||
| 311 | */ | ||
| 312 | if (btrfs_header_nritems(leaf) == 0) | ||
| 313 | break; | ||
| 314 | /* | ||
| 315 | * we need to copy the key out so that | ||
| 316 | * we are sure the next search advances | ||
| 317 | * us forward in the btree. | ||
| 318 | */ | ||
| 319 | btrfs_item_key_to_cpu(leaf, &key, 0); | ||
| 307 | btrfs_release_path(fs_info->extent_root, path); | 320 | btrfs_release_path(fs_info->extent_root, path); |
| 308 | up_read(&fs_info->extent_commit_sem); | 321 | up_read(&fs_info->extent_commit_sem); |
| 309 | schedule_timeout(1); | 322 | schedule_timeout(1); |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index af99b78b288e..5edcee3a617f 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
| @@ -414,11 +414,29 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro | |||
| 414 | u64 *offset, u64 *bytes) | 414 | u64 *offset, u64 *bytes) |
| 415 | { | 415 | { |
| 416 | u64 end; | 416 | u64 end; |
| 417 | u64 search_start, search_bytes; | ||
| 418 | int ret; | ||
| 417 | 419 | ||
| 418 | again: | 420 | again: |
| 419 | end = bitmap_info->offset + | 421 | end = bitmap_info->offset + |
| 420 | (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1; | 422 | (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1; |
| 421 | 423 | ||
| 424 | /* | ||
| 425 | * XXX - this can go away after a few releases. | ||
| 426 | * | ||
| 427 | * since the only user of btrfs_remove_free_space is the tree logging | ||
| 428 | * stuff, and the only way to test that is under crash conditions, we | ||
| 429 | * want to have this debug stuff here just in case somethings not | ||
| 430 | * working. Search the bitmap for the space we are trying to use to | ||
| 431 | * make sure its actually there. If its not there then we need to stop | ||
| 432 | * because something has gone wrong. | ||
| 433 | */ | ||
| 434 | search_start = *offset; | ||
| 435 | search_bytes = *bytes; | ||
| 436 | ret = search_bitmap(block_group, bitmap_info, &search_start, | ||
| 437 | &search_bytes); | ||
| 438 | BUG_ON(ret < 0 || search_start != *offset); | ||
| 439 | |||
| 422 | if (*offset > bitmap_info->offset && *offset + *bytes > end) { | 440 | if (*offset > bitmap_info->offset && *offset + *bytes > end) { |
| 423 | bitmap_clear_bits(block_group, bitmap_info, *offset, | 441 | bitmap_clear_bits(block_group, bitmap_info, *offset, |
| 424 | end - *offset + 1); | 442 | end - *offset + 1); |
| @@ -430,6 +448,7 @@ again: | |||
| 430 | } | 448 | } |
| 431 | 449 | ||
| 432 | if (*bytes) { | 450 | if (*bytes) { |
| 451 | struct rb_node *next = rb_next(&bitmap_info->offset_index); | ||
| 433 | if (!bitmap_info->bytes) { | 452 | if (!bitmap_info->bytes) { |
| 434 | unlink_free_space(block_group, bitmap_info); | 453 | unlink_free_space(block_group, bitmap_info); |
| 435 | kfree(bitmap_info->bitmap); | 454 | kfree(bitmap_info->bitmap); |
| @@ -438,16 +457,36 @@ again: | |||
| 438 | recalculate_thresholds(block_group); | 457 | recalculate_thresholds(block_group); |
| 439 | } | 458 | } |
| 440 | 459 | ||
| 441 | bitmap_info = tree_search_offset(block_group, | 460 | /* |
| 442 | offset_to_bitmap(block_group, | 461 | * no entry after this bitmap, but we still have bytes to |
| 443 | *offset), | 462 | * remove, so something has gone wrong. |
| 444 | 1, 0); | 463 | */ |
| 445 | if (!bitmap_info) | 464 | if (!next) |
| 446 | return -EINVAL; | 465 | return -EINVAL; |
| 447 | 466 | ||
| 467 | bitmap_info = rb_entry(next, struct btrfs_free_space, | ||
| 468 | offset_index); | ||
| 469 | |||
| 470 | /* | ||
| 471 | * if the next entry isn't a bitmap we need to return to let the | ||
| 472 | * extent stuff do its work. | ||
| 473 | */ | ||
| 448 | if (!bitmap_info->bitmap) | 474 | if (!bitmap_info->bitmap) |
| 449 | return -EAGAIN; | 475 | return -EAGAIN; |
| 450 | 476 | ||
| 477 | /* | ||
| 478 | * Ok the next item is a bitmap, but it may not actually hold | ||
| 479 | * the information for the rest of this free space stuff, so | ||
| 480 | * look for it, and if we don't find it return so we can try | ||
| 481 | * everything over again. | ||
| 482 | */ | ||
| 483 | search_start = *offset; | ||
| 484 | search_bytes = *bytes; | ||
| 485 | ret = search_bitmap(block_group, bitmap_info, &search_start, | ||
| 486 | &search_bytes); | ||
| 487 | if (ret < 0 || search_start != *offset) | ||
| 488 | return -EAGAIN; | ||
| 489 | |||
| 451 | goto again; | 490 | goto again; |
| 452 | } else if (!bitmap_info->bytes) { | 491 | } else if (!bitmap_info->bytes) { |
| 453 | unlink_free_space(block_group, bitmap_info); | 492 | unlink_free_space(block_group, bitmap_info); |
| @@ -644,8 +683,17 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
| 644 | again: | 683 | again: |
| 645 | info = tree_search_offset(block_group, offset, 0, 0); | 684 | info = tree_search_offset(block_group, offset, 0, 0); |
| 646 | if (!info) { | 685 | if (!info) { |
| 647 | WARN_ON(1); | 686 | /* |
| 648 | goto out_lock; | 687 | * oops didn't find an extent that matched the space we wanted |
| 688 | * to remove, look for a bitmap instead | ||
| 689 | */ | ||
| 690 | info = tree_search_offset(block_group, | ||
| 691 | offset_to_bitmap(block_group, offset), | ||
| 692 | 1, 0); | ||
| 693 | if (!info) { | ||
| 694 | WARN_ON(1); | ||
| 695 | goto out_lock; | ||
| 696 | } | ||
| 649 | } | 697 | } |
| 650 | 698 | ||
| 651 | if (info->bytes < bytes && rb_next(&info->offset_index)) { | 699 | if (info->bytes < bytes && rb_next(&info->offset_index)) { |
| @@ -957,8 +1005,15 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, | |||
| 957 | if (cluster->block_group != block_group) | 1005 | if (cluster->block_group != block_group) |
| 958 | goto out; | 1006 | goto out; |
| 959 | 1007 | ||
| 960 | entry = tree_search_offset(block_group, search_start, 0, 0); | 1008 | /* |
| 961 | 1009 | * search_start is the beginning of the bitmap, but at some point it may | |
| 1010 | * be a good idea to point to the actual start of the free area in the | ||
| 1011 | * bitmap, so do the offset_to_bitmap trick anyway, and set bitmap_only | ||
| 1012 | * to 1 to make sure we get the bitmap entry | ||
| 1013 | */ | ||
| 1014 | entry = tree_search_offset(block_group, | ||
| 1015 | offset_to_bitmap(block_group, search_start), | ||
| 1016 | 1, 0); | ||
| 962 | if (!entry || !entry->bitmap) | 1017 | if (!entry || !entry->bitmap) |
| 963 | goto out; | 1018 | goto out; |
| 964 | 1019 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 56fe83fa60c4..272b9b2bea86 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -4785,8 +4785,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 4785 | * and the replacement file is large. Start IO on it now so | 4785 | * and the replacement file is large. Start IO on it now so |
| 4786 | * we don't add too much work to the end of the transaction | 4786 | * we don't add too much work to the end of the transaction |
| 4787 | */ | 4787 | */ |
| 4788 | if (new_inode && old_inode && S_ISREG(old_inode->i_mode) && | 4788 | if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size && |
| 4789 | new_inode->i_size && | ||
| 4790 | old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | 4789 | old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) |
| 4791 | filemap_flush(old_inode->i_mapping); | 4790 | filemap_flush(old_inode->i_mapping); |
| 4792 | 4791 | ||
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index e71264d1c2c9..c04f7f212602 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -2553,8 +2553,13 @@ int relocate_inode_pages(struct inode *inode, u64 start, u64 len) | |||
| 2553 | last_index = (start + len - 1) >> PAGE_CACHE_SHIFT; | 2553 | last_index = (start + len - 1) >> PAGE_CACHE_SHIFT; |
| 2554 | 2554 | ||
| 2555 | /* make sure the dirty trick played by the caller work */ | 2555 | /* make sure the dirty trick played by the caller work */ |
| 2556 | ret = invalidate_inode_pages2_range(inode->i_mapping, | 2556 | while (1) { |
| 2557 | first_index, last_index); | 2557 | ret = invalidate_inode_pages2_range(inode->i_mapping, |
| 2558 | first_index, last_index); | ||
| 2559 | if (ret != -EBUSY) | ||
| 2560 | break; | ||
| 2561 | schedule_timeout(HZ/10); | ||
| 2562 | } | ||
| 2558 | if (ret) | 2563 | if (ret) |
| 2559 | goto out_unlock; | 2564 | goto out_unlock; |
| 2560 | 2565 | ||
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c index ecfbce836d32..3e2b90eaa239 100644 --- a/fs/btrfs/zlib.c +++ b/fs/btrfs/zlib.c | |||
| @@ -208,7 +208,7 @@ int btrfs_zlib_compress_pages(struct address_space *mapping, | |||
| 208 | *total_in = 0; | 208 | *total_in = 0; |
| 209 | 209 | ||
| 210 | workspace = find_zlib_workspace(); | 210 | workspace = find_zlib_workspace(); |
| 211 | if (!workspace) | 211 | if (IS_ERR(workspace)) |
| 212 | return -1; | 212 | return -1; |
| 213 | 213 | ||
| 214 | if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) { | 214 | if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) { |
| @@ -366,7 +366,7 @@ int btrfs_zlib_decompress_biovec(struct page **pages_in, | |||
| 366 | char *kaddr; | 366 | char *kaddr; |
| 367 | 367 | ||
| 368 | workspace = find_zlib_workspace(); | 368 | workspace = find_zlib_workspace(); |
| 369 | if (!workspace) | 369 | if (IS_ERR(workspace)) |
| 370 | return -ENOMEM; | 370 | return -ENOMEM; |
| 371 | 371 | ||
| 372 | data_in = kmap(pages_in[page_in_index]); | 372 | data_in = kmap(pages_in[page_in_index]); |
| @@ -547,7 +547,7 @@ int btrfs_zlib_decompress(unsigned char *data_in, | |||
| 547 | return -ENOMEM; | 547 | return -ENOMEM; |
| 548 | 548 | ||
| 549 | workspace = find_zlib_workspace(); | 549 | workspace = find_zlib_workspace(); |
| 550 | if (!workspace) | 550 | if (IS_ERR(workspace)) |
| 551 | return -ENOMEM; | 551 | return -ENOMEM; |
| 552 | 552 | ||
| 553 | workspace->inf_strm.next_in = data_in; | 553 | workspace->inf_strm.next_in = data_in; |
