diff options
author | Chris Mason <chris.mason@oracle.com> | 2011-06-03 01:26:53 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-06-04 08:03:43 -0400 |
commit | 211f96c24f117fcc6e9e2431e40d92f4de22625e (patch) | |
tree | 9f73c5419e905066653660ec33f8d5efeaa3a148 /fs/btrfs/free-space-cache.c | |
parent | 17aca1c987cff89dc4279371857035da902c8854 (diff) |
Btrfs: make sure we don't overflow the free space cache crc page
The free space cache uses only one page for crcs right now,
which means we can't have a cache file bigger than the
crcs we can fit in the first page. This adds a check to
enforce that restriction.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index dd38d4c3a599..1cb72394498c 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -590,10 +590,25 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
590 | 590 | ||
591 | num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> | 591 | num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> |
592 | PAGE_CACHE_SHIFT; | 592 | PAGE_CACHE_SHIFT; |
593 | |||
594 | /* Since the first page has all of our checksums and our generation we | ||
595 | * need to calculate the offset into the page that we can start writing | ||
596 | * our entries. | ||
597 | */ | ||
598 | first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64); | ||
599 | |||
593 | filemap_write_and_wait(inode->i_mapping); | 600 | filemap_write_and_wait(inode->i_mapping); |
594 | btrfs_wait_ordered_range(inode, inode->i_size & | 601 | btrfs_wait_ordered_range(inode, inode->i_size & |
595 | ~(root->sectorsize - 1), (u64)-1); | 602 | ~(root->sectorsize - 1), (u64)-1); |
596 | 603 | ||
604 | /* make sure we don't overflow that first page */ | ||
605 | if (first_page_offset + sizeof(struct btrfs_free_space_entry) >= PAGE_CACHE_SIZE) { | ||
606 | /* this is really the same as running out of space, where we also return 0 */ | ||
607 | printk(KERN_CRIT "Btrfs: free space cache was too big for the crc page\n"); | ||
608 | ret = 0; | ||
609 | goto out_update; | ||
610 | } | ||
611 | |||
597 | /* We need a checksum per page. */ | 612 | /* We need a checksum per page. */ |
598 | crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS); | 613 | crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS); |
599 | if (!crc) | 614 | if (!crc) |
@@ -605,12 +620,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
605 | return -1; | 620 | return -1; |
606 | } | 621 | } |
607 | 622 | ||
608 | /* Since the first page has all of our checksums and our generation we | ||
609 | * need to calculate the offset into the page that we can start writing | ||
610 | * our entries. | ||
611 | */ | ||
612 | first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64); | ||
613 | |||
614 | /* Get the cluster for this block_group if it exists */ | 623 | /* Get the cluster for this block_group if it exists */ |
615 | if (block_group && !list_empty(&block_group->cluster_list)) | 624 | if (block_group && !list_empty(&block_group->cluster_list)) |
616 | cluster = list_entry(block_group->cluster_list.next, | 625 | cluster = list_entry(block_group->cluster_list.next, |
@@ -872,12 +881,14 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
872 | ret = 1; | 881 | ret = 1; |
873 | 882 | ||
874 | out_free: | 883 | out_free: |
884 | kfree(checksums); | ||
885 | kfree(pages); | ||
886 | |||
887 | out_update: | ||
875 | if (ret != 1) { | 888 | if (ret != 1) { |
876 | invalidate_inode_pages2_range(inode->i_mapping, 0, index); | 889 | invalidate_inode_pages2_range(inode->i_mapping, 0, index); |
877 | BTRFS_I(inode)->generation = 0; | 890 | BTRFS_I(inode)->generation = 0; |
878 | } | 891 | } |
879 | kfree(checksums); | ||
880 | kfree(pages); | ||
881 | btrfs_update_inode(trans, root, inode); | 892 | btrfs_update_inode(trans, root, inode); |
882 | return ret; | 893 | return ret; |
883 | } | 894 | } |