diff options
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
| -rw-r--r-- | fs/btrfs/free-space-cache.c | 119 |
1 files changed, 56 insertions, 63 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index f561c953205b..11d2e9cea09e 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
| @@ -508,6 +508,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 508 | struct inode *inode; | 508 | struct inode *inode; |
| 509 | struct rb_node *node; | 509 | struct rb_node *node; |
| 510 | struct list_head *pos, *n; | 510 | struct list_head *pos, *n; |
| 511 | struct page **pages; | ||
| 511 | struct page *page; | 512 | struct page *page; |
| 512 | struct extent_state *cached_state = NULL; | 513 | struct extent_state *cached_state = NULL; |
| 513 | struct btrfs_free_cluster *cluster = NULL; | 514 | struct btrfs_free_cluster *cluster = NULL; |
| @@ -517,13 +518,13 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 517 | u64 start, end, len; | 518 | u64 start, end, len; |
| 518 | u64 bytes = 0; | 519 | u64 bytes = 0; |
| 519 | u32 *crc, *checksums; | 520 | u32 *crc, *checksums; |
| 520 | pgoff_t index = 0, last_index = 0; | ||
| 521 | unsigned long first_page_offset; | 521 | unsigned long first_page_offset; |
| 522 | int num_checksums; | 522 | int index = 0, num_pages = 0; |
| 523 | int entries = 0; | 523 | int entries = 0; |
| 524 | int bitmaps = 0; | 524 | int bitmaps = 0; |
| 525 | int ret = 0; | 525 | int ret = 0; |
| 526 | bool next_page = false; | 526 | bool next_page = false; |
| 527 | bool out_of_space = false; | ||
| 527 | 528 | ||
| 528 | root = root->fs_info->tree_root; | 529 | root = root->fs_info->tree_root; |
| 529 | 530 | ||
| @@ -551,24 +552,31 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 551 | return 0; | 552 | return 0; |
| 552 | } | 553 | } |
| 553 | 554 | ||
| 554 | last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT; | 555 | num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> |
| 556 | PAGE_CACHE_SHIFT; | ||
| 555 | filemap_write_and_wait(inode->i_mapping); | 557 | filemap_write_and_wait(inode->i_mapping); |
| 556 | btrfs_wait_ordered_range(inode, inode->i_size & | 558 | btrfs_wait_ordered_range(inode, inode->i_size & |
| 557 | ~(root->sectorsize - 1), (u64)-1); | 559 | ~(root->sectorsize - 1), (u64)-1); |
| 558 | 560 | ||
| 559 | /* We need a checksum per page. */ | 561 | /* We need a checksum per page. */ |
| 560 | num_checksums = i_size_read(inode) / PAGE_CACHE_SIZE; | 562 | crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS); |
| 561 | crc = checksums = kzalloc(sizeof(u32) * num_checksums, GFP_NOFS); | ||
| 562 | if (!crc) { | 563 | if (!crc) { |
| 563 | iput(inode); | 564 | iput(inode); |
| 564 | return 0; | 565 | return 0; |
| 565 | } | 566 | } |
| 566 | 567 | ||
| 568 | pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS); | ||
| 569 | if (!pages) { | ||
| 570 | kfree(crc); | ||
| 571 | iput(inode); | ||
| 572 | return 0; | ||
| 573 | } | ||
| 574 | |||
| 567 | /* Since the first page has all of our checksums and our generation we | 575 | /* Since the first page has all of our checksums and our generation we |
| 568 | * need to calculate the offset into the page that we can start writing | 576 | * need to calculate the offset into the page that we can start writing |
| 569 | * our entries. | 577 | * our entries. |
| 570 | */ | 578 | */ |
| 571 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); | 579 | first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64); |
| 572 | 580 | ||
| 573 | /* Get the cluster for this block_group if it exists */ | 581 | /* Get the cluster for this block_group if it exists */ |
| 574 | if (!list_empty(&block_group->cluster_list)) | 582 | if (!list_empty(&block_group->cluster_list)) |
| @@ -590,20 +598,18 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 590 | * after find_get_page at this point. Just putting this here so people | 598 | * after find_get_page at this point. Just putting this here so people |
| 591 | * know and don't freak out. | 599 | * know and don't freak out. |
| 592 | */ | 600 | */ |
| 593 | while (index <= last_index) { | 601 | while (index < num_pages) { |
| 594 | page = grab_cache_page(inode->i_mapping, index); | 602 | page = grab_cache_page(inode->i_mapping, index); |
| 595 | if (!page) { | 603 | if (!page) { |
| 596 | pgoff_t i = 0; | 604 | int i; |
| 597 | 605 | ||
| 598 | while (i < index) { | 606 | for (i = 0; i < num_pages; i++) { |
| 599 | page = find_get_page(inode->i_mapping, i); | 607 | unlock_page(pages[i]); |
| 600 | unlock_page(page); | 608 | page_cache_release(pages[i]); |
| 601 | page_cache_release(page); | ||
| 602 | page_cache_release(page); | ||
| 603 | i++; | ||
| 604 | } | 609 | } |
| 605 | goto out_free; | 610 | goto out_free; |
| 606 | } | 611 | } |
| 612 | pages[index] = page; | ||
| 607 | index++; | 613 | index++; |
| 608 | } | 614 | } |
| 609 | 615 | ||
| @@ -631,7 +637,12 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 631 | offset = start_offset; | 637 | offset = start_offset; |
| 632 | } | 638 | } |
| 633 | 639 | ||
| 634 | page = find_get_page(inode->i_mapping, index); | 640 | if (index >= num_pages) { |
| 641 | out_of_space = true; | ||
| 642 | break; | ||
| 643 | } | ||
| 644 | |||
| 645 | page = pages[index]; | ||
| 635 | 646 | ||
| 636 | addr = kmap(page); | 647 | addr = kmap(page); |
| 637 | entry = addr + start_offset; | 648 | entry = addr + start_offset; |
| @@ -708,23 +719,6 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 708 | 719 | ||
| 709 | bytes += PAGE_CACHE_SIZE; | 720 | bytes += PAGE_CACHE_SIZE; |
| 710 | 721 | ||
| 711 | ClearPageChecked(page); | ||
| 712 | set_page_extent_mapped(page); | ||
| 713 | SetPageUptodate(page); | ||
| 714 | set_page_dirty(page); | ||
| 715 | |||
| 716 | /* | ||
| 717 | * We need to release our reference we got for grab_cache_page, | ||
| 718 | * except for the first page which will hold our checksums, we | ||
| 719 | * do that below. | ||
| 720 | */ | ||
| 721 | if (index != 0) { | ||
| 722 | unlock_page(page); | ||
| 723 | page_cache_release(page); | ||
| 724 | } | ||
| 725 | |||
| 726 | page_cache_release(page); | ||
| 727 | |||
| 728 | index++; | 722 | index++; |
| 729 | } while (node || next_page); | 723 | } while (node || next_page); |
| 730 | 724 | ||
| @@ -734,7 +728,11 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 734 | struct btrfs_free_space *entry = | 728 | struct btrfs_free_space *entry = |
| 735 | list_entry(pos, struct btrfs_free_space, list); | 729 | list_entry(pos, struct btrfs_free_space, list); |
| 736 | 730 | ||
| 737 | page = find_get_page(inode->i_mapping, index); | 731 | if (index >= num_pages) { |
| 732 | out_of_space = true; | ||
| 733 | break; | ||
| 734 | } | ||
| 735 | page = pages[index]; | ||
| 738 | 736 | ||
| 739 | addr = kmap(page); | 737 | addr = kmap(page); |
| 740 | memcpy(addr, entry->bitmap, PAGE_CACHE_SIZE); | 738 | memcpy(addr, entry->bitmap, PAGE_CACHE_SIZE); |
| @@ -745,64 +743,58 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
| 745 | crc++; | 743 | crc++; |
| 746 | bytes += PAGE_CACHE_SIZE; | 744 | bytes += PAGE_CACHE_SIZE; |
| 747 | 745 | ||
| 748 | ClearPageChecked(page); | ||
| 749 | set_page_extent_mapped(page); | ||
| 750 | SetPageUptodate(page); | ||
| 751 | set_page_dirty(page); | ||
| 752 | unlock_page(page); | ||
| 753 | page_cache_release(page); | ||
| 754 | page_cache_release(page); | ||
| 755 | list_del_init(&entry->list); | 746 | list_del_init(&entry->list); |
| 756 | index++; | 747 | index++; |
| 757 | } | 748 | } |
| 758 | 749 | ||
| 750 | if (out_of_space) { | ||
| 751 | btrfs_drop_pages(pages, num_pages); | ||
| 752 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, | ||
| 753 | i_size_read(inode) - 1, &cached_state, | ||
| 754 | GFP_NOFS); | ||
| 755 | ret = 0; | ||
| 756 | goto out_free; | ||
| 757 | } | ||
| 758 | |||
| 759 | /* Zero out the rest of the pages just to make sure */ | 759 | /* Zero out the rest of the pages just to make sure */ |
| 760 | while (index <= last_index) { | 760 | while (index < num_pages) { |
| 761 | void *addr; | 761 | void *addr; |
| 762 | 762 | ||
| 763 | page = find_get_page(inode->i_mapping, index); | 763 | page = pages[index]; |
| 764 | |||
| 765 | addr = kmap(page); | 764 | addr = kmap(page); |
| 766 | memset(addr, 0, PAGE_CACHE_SIZE); | 765 | memset(addr, 0, PAGE_CACHE_SIZE); |
| 767 | kunmap(page); | 766 | kunmap(page); |
| 768 | ClearPageChecked(page); | ||
| 769 | set_page_extent_mapped(page); | ||
| 770 | SetPageUptodate(page); | ||
| 771 | set_page_dirty(page); | ||
| 772 | unlock_page(page); | ||
| 773 | page_cache_release(page); | ||
| 774 | page_cache_release(page); | ||
| 775 | bytes += PAGE_CACHE_SIZE; | 767 | bytes += PAGE_CACHE_SIZE; |
| 776 | index++; | 768 | index++; |
| 777 | } | 769 | } |
| 778 | 770 | ||
| 779 | btrfs_set_extent_delalloc(inode, 0, bytes - 1, &cached_state); | ||
| 780 | |||
| 781 | /* Write the checksums and trans id to the first page */ | 771 | /* Write the checksums and trans id to the first page */ |
| 782 | { | 772 | { |
| 783 | void *addr; | 773 | void *addr; |
| 784 | u64 *gen; | 774 | u64 *gen; |
| 785 | 775 | ||
| 786 | page = find_get_page(inode->i_mapping, 0); | 776 | page = pages[0]; |
| 787 | 777 | ||
| 788 | addr = kmap(page); | 778 | addr = kmap(page); |
| 789 | memcpy(addr, checksums, sizeof(u32) * num_checksums); | 779 | memcpy(addr, checksums, sizeof(u32) * num_pages); |
| 790 | gen = addr + (sizeof(u32) * num_checksums); | 780 | gen = addr + (sizeof(u32) * num_pages); |
| 791 | *gen = trans->transid; | 781 | *gen = trans->transid; |
| 792 | kunmap(page); | 782 | kunmap(page); |
| 793 | ClearPageChecked(page); | ||
| 794 | set_page_extent_mapped(page); | ||
| 795 | SetPageUptodate(page); | ||
| 796 | set_page_dirty(page); | ||
| 797 | unlock_page(page); | ||
| 798 | page_cache_release(page); | ||
| 799 | page_cache_release(page); | ||
| 800 | } | 783 | } |
| 801 | BTRFS_I(inode)->generation = trans->transid; | ||
| 802 | 784 | ||
| 785 | ret = btrfs_dirty_pages(root, inode, pages, num_pages, 0, | ||
| 786 | bytes, &cached_state); | ||
| 787 | btrfs_drop_pages(pages, num_pages); | ||
| 803 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, | 788 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, |
| 804 | i_size_read(inode) - 1, &cached_state, GFP_NOFS); | 789 | i_size_read(inode) - 1, &cached_state, GFP_NOFS); |
| 805 | 790 | ||
| 791 | if (ret) { | ||
| 792 | ret = 0; | ||
| 793 | goto out_free; | ||
| 794 | } | ||
| 795 | |||
| 796 | BTRFS_I(inode)->generation = trans->transid; | ||
| 797 | |||
| 806 | filemap_write_and_wait(inode->i_mapping); | 798 | filemap_write_and_wait(inode->i_mapping); |
| 807 | 799 | ||
| 808 | key.objectid = BTRFS_FREE_SPACE_OBJECTID; | 800 | key.objectid = BTRFS_FREE_SPACE_OBJECTID; |
| @@ -853,6 +845,7 @@ out_free: | |||
| 853 | BTRFS_I(inode)->generation = 0; | 845 | BTRFS_I(inode)->generation = 0; |
| 854 | } | 846 | } |
| 855 | kfree(checksums); | 847 | kfree(checksums); |
| 848 | kfree(pages); | ||
| 856 | btrfs_update_inode(trans, root, inode); | 849 | btrfs_update_inode(trans, root, inode); |
| 857 | iput(inode); | 850 | iput(inode); |
| 858 | return ret; | 851 | return ret; |
