aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 6e953de83f08..75533adef998 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4728,16 +4728,16 @@ err:
4728} 4728}
4729 4729
4730struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, 4730struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
4731 u64 start) 4731 u64 start, u32 nodesize)
4732{ 4732{
4733 unsigned long len; 4733 unsigned long len;
4734 4734
4735 if (!fs_info) { 4735 if (!fs_info) {
4736 /* 4736 /*
4737 * Called only from tests that don't always have a fs_info 4737 * Called only from tests that don't always have a fs_info
4738 * available, but we know that nodesize is 4096 4738 * available
4739 */ 4739 */
4740 len = 4096; 4740 len = nodesize;
4741 } else { 4741 } else {
4742 len = fs_info->tree_root->nodesize; 4742 len = fs_info->tree_root->nodesize;
4743 } 4743 }
@@ -4833,7 +4833,7 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info,
4833 4833
4834#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS 4834#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
4835struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, 4835struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
4836 u64 start) 4836 u64 start, u32 nodesize)
4837{ 4837{
4838 struct extent_buffer *eb, *exists = NULL; 4838 struct extent_buffer *eb, *exists = NULL;
4839 int ret; 4839 int ret;
@@ -4841,7 +4841,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
4841 eb = find_extent_buffer(fs_info, start); 4841 eb = find_extent_buffer(fs_info, start);
4842 if (eb) 4842 if (eb)
4843 return eb; 4843 return eb;
4844 eb = alloc_dummy_extent_buffer(fs_info, start); 4844 eb = alloc_dummy_extent_buffer(fs_info, start, nodesize);
4845 if (!eb) 4845 if (!eb)
4846 return NULL; 4846 return NULL;
4847 eb->fs_info = fs_info; 4847 eb->fs_info = fs_info;
@@ -4892,18 +4892,25 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
4892 int uptodate = 1; 4892 int uptodate = 1;
4893 int ret; 4893 int ret;
4894 4894
4895 if (!IS_ALIGNED(start, fs_info->tree_root->sectorsize)) {
4896 btrfs_err(fs_info, "bad tree block start %llu", start);
4897 return ERR_PTR(-EINVAL);
4898 }
4899
4895 eb = find_extent_buffer(fs_info, start); 4900 eb = find_extent_buffer(fs_info, start);
4896 if (eb) 4901 if (eb)
4897 return eb; 4902 return eb;
4898 4903
4899 eb = __alloc_extent_buffer(fs_info, start, len); 4904 eb = __alloc_extent_buffer(fs_info, start, len);
4900 if (!eb) 4905 if (!eb)
4901 return NULL; 4906 return ERR_PTR(-ENOMEM);
4902 4907
4903 for (i = 0; i < num_pages; i++, index++) { 4908 for (i = 0; i < num_pages; i++, index++) {
4904 p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL); 4909 p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL);
4905 if (!p) 4910 if (!p) {
4911 exists = ERR_PTR(-ENOMEM);
4906 goto free_eb; 4912 goto free_eb;
4913 }
4907 4914
4908 spin_lock(&mapping->private_lock); 4915 spin_lock(&mapping->private_lock);
4909 if (PagePrivate(p)) { 4916 if (PagePrivate(p)) {
@@ -4948,8 +4955,10 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
4948 set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); 4955 set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
4949again: 4956again:
4950 ret = radix_tree_preload(GFP_NOFS); 4957 ret = radix_tree_preload(GFP_NOFS);
4951 if (ret) 4958 if (ret) {
4959 exists = ERR_PTR(ret);
4952 goto free_eb; 4960 goto free_eb;
4961 }
4953 4962
4954 spin_lock(&fs_info->buffer_lock); 4963 spin_lock(&fs_info->buffer_lock);
4955 ret = radix_tree_insert(&fs_info->buffer_radix, 4964 ret = radix_tree_insert(&fs_info->buffer_radix,
@@ -5333,6 +5342,11 @@ int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
5333 return ret; 5342 return ret;
5334} 5343}
5335 5344
5345/*
5346 * return 0 if the item is found within a page.
5347 * return 1 if the item spans two pages.
5348 * return -EINVAL otherwise.
5349 */
5336int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, 5350int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
5337 unsigned long min_len, char **map, 5351 unsigned long min_len, char **map,
5338 unsigned long *map_start, 5352 unsigned long *map_start,
@@ -5347,7 +5361,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
5347 PAGE_SHIFT; 5361 PAGE_SHIFT;
5348 5362
5349 if (i != end_i) 5363 if (i != end_i)
5350 return -EINVAL; 5364 return 1;
5351 5365
5352 if (i == 0) { 5366 if (i == 0) {
5353 offset = start_offset; 5367 offset = start_offset;