aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@fusionio.com>2013-02-20 14:06:05 -0500
committerChris Mason <chris.mason@fusionio.com>2013-02-20 14:06:05 -0500
commite942f883bc6651d50be139477baf6fb0eed3d5bb (patch)
treee1d19783e9c8b42198a69c17c9719fb90f302847 /fs/btrfs/extent_io.c
parentb2c6b3e0611c58fbeb6b9c0892b6249f7bdfaf6b (diff)
parent0e4e02636611dbf89a2f36320a32054f9936d6cb (diff)
Merge branch 'raid56-experimental' into for-linus-3.9
Signed-off-by: Chris Mason <chris.mason@fusionio.com> Conflicts: fs/btrfs/ctree.h fs/btrfs/extent-tree.c fs/btrfs/inode.c fs/btrfs/volumes.c
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 5c00d6aeae75..66f999b97cbb 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1895,13 +1895,11 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec,
1895 if (ret) 1895 if (ret)
1896 err = ret; 1896 err = ret;
1897 1897
1898 if (did_repair) { 1898 ret = clear_extent_bits(&BTRFS_I(inode)->io_tree, rec->start,
1899 ret = clear_extent_bits(&BTRFS_I(inode)->io_tree, rec->start, 1899 rec->start + rec->len - 1,
1900 rec->start + rec->len - 1, 1900 EXTENT_DAMAGED, GFP_NOFS);
1901 EXTENT_DAMAGED, GFP_NOFS); 1901 if (ret && !err)
1902 if (ret && !err) 1902 err = ret;
1903 err = ret;
1904 }
1905 1903
1906 kfree(rec); 1904 kfree(rec);
1907 return err; 1905 return err;
@@ -1932,10 +1930,15 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
1932 u64 map_length = 0; 1930 u64 map_length = 0;
1933 u64 sector; 1931 u64 sector;
1934 struct btrfs_bio *bbio = NULL; 1932 struct btrfs_bio *bbio = NULL;
1933 struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
1935 int ret; 1934 int ret;
1936 1935
1937 BUG_ON(!mirror_num); 1936 BUG_ON(!mirror_num);
1938 1937
1938 /* we can't repair anything in raid56 yet */
1939 if (btrfs_is_parity_mirror(map_tree, logical, length, mirror_num))
1940 return 0;
1941
1939 bio = bio_alloc(GFP_NOFS, 1); 1942 bio = bio_alloc(GFP_NOFS, 1);
1940 if (!bio) 1943 if (!bio)
1941 return -EIO; 1944 return -EIO;
@@ -2052,6 +2055,7 @@ static int clean_io_failure(u64 start, struct page *page)
2052 failrec->failed_mirror); 2055 failrec->failed_mirror);
2053 did_repair = !ret; 2056 did_repair = !ret;
2054 } 2057 }
2058 ret = 0;
2055 } 2059 }
2056 2060
2057out: 2061out:
@@ -2487,13 +2491,13 @@ static int __must_check submit_one_bio(int rw, struct bio *bio,
2487 return ret; 2491 return ret;
2488} 2492}
2489 2493
2490static int merge_bio(struct extent_io_tree *tree, struct page *page, 2494static int merge_bio(int rw, struct extent_io_tree *tree, struct page *page,
2491 unsigned long offset, size_t size, struct bio *bio, 2495 unsigned long offset, size_t size, struct bio *bio,
2492 unsigned long bio_flags) 2496 unsigned long bio_flags)
2493{ 2497{
2494 int ret = 0; 2498 int ret = 0;
2495 if (tree->ops && tree->ops->merge_bio_hook) 2499 if (tree->ops && tree->ops->merge_bio_hook)
2496 ret = tree->ops->merge_bio_hook(page, offset, size, bio, 2500 ret = tree->ops->merge_bio_hook(rw, page, offset, size, bio,
2497 bio_flags); 2501 bio_flags);
2498 BUG_ON(ret < 0); 2502 BUG_ON(ret < 0);
2499 return ret; 2503 return ret;
@@ -2528,7 +2532,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
2528 sector; 2532 sector;
2529 2533
2530 if (prev_bio_flags != bio_flags || !contig || 2534 if (prev_bio_flags != bio_flags || !contig ||
2531 merge_bio(tree, page, offset, page_size, bio, bio_flags) || 2535 merge_bio(rw, tree, page, offset, page_size, bio, bio_flags) ||
2532 bio_add_page(bio, page, page_size, offset) < page_size) { 2536 bio_add_page(bio, page, page_size, offset) < page_size) {
2533 ret = submit_one_bio(rw, bio, mirror_num, 2537 ret = submit_one_bio(rw, bio, mirror_num,
2534 prev_bio_flags); 2538 prev_bio_flags);
@@ -4162,6 +4166,7 @@ static inline void btrfs_release_extent_buffer(struct extent_buffer *eb)
4162 4166
4163static void check_buffer_tree_ref(struct extent_buffer *eb) 4167static void check_buffer_tree_ref(struct extent_buffer *eb)
4164{ 4168{
4169 int refs;
4165 /* the ref bit is tricky. We have to make sure it is set 4170 /* the ref bit is tricky. We have to make sure it is set
4166 * if we have the buffer dirty. Otherwise the 4171 * if we have the buffer dirty. Otherwise the
4167 * code to free a buffer can end up dropping a dirty 4172 * code to free a buffer can end up dropping a dirty
@@ -4182,6 +4187,10 @@ static void check_buffer_tree_ref(struct extent_buffer *eb)
4182 * So bump the ref count first, then set the bit. If someone 4187 * So bump the ref count first, then set the bit. If someone
4183 * beat us to it, drop the ref we added. 4188 * beat us to it, drop the ref we added.
4184 */ 4189 */
4190 refs = atomic_read(&eb->refs);
4191 if (refs >= 2 && test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
4192 return;
4193
4185 spin_lock(&eb->refs_lock); 4194 spin_lock(&eb->refs_lock);
4186 if (!test_and_set_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) 4195 if (!test_and_set_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
4187 atomic_inc(&eb->refs); 4196 atomic_inc(&eb->refs);
@@ -4383,9 +4392,20 @@ static int release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
4383 4392
4384void free_extent_buffer(struct extent_buffer *eb) 4393void free_extent_buffer(struct extent_buffer *eb)
4385{ 4394{
4395 int refs;
4396 int old;
4386 if (!eb) 4397 if (!eb)
4387 return; 4398 return;
4388 4399
4400 while (1) {
4401 refs = atomic_read(&eb->refs);
4402 if (refs <= 3)
4403 break;
4404 old = atomic_cmpxchg(&eb->refs, refs, refs - 1);
4405 if (old == refs)
4406 return;
4407 }
4408
4389 spin_lock(&eb->refs_lock); 4409 spin_lock(&eb->refs_lock);
4390 if (atomic_read(&eb->refs) == 2 && 4410 if (atomic_read(&eb->refs) == 2 &&
4391 test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags)) 4411 test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags))