diff options
author | Chris Mason <chris.mason@fusionio.com> | 2013-02-20 14:06:05 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-02-20 14:06:05 -0500 |
commit | e942f883bc6651d50be139477baf6fb0eed3d5bb (patch) | |
tree | e1d19783e9c8b42198a69c17c9719fb90f302847 /fs/btrfs/extent_io.c | |
parent | b2c6b3e0611c58fbeb6b9c0892b6249f7bdfaf6b (diff) | |
parent | 0e4e02636611dbf89a2f36320a32054f9936d6cb (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.c | 40 |
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 | ||
2057 | out: | 2061 | out: |
@@ -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 | ||
2490 | static int merge_bio(struct extent_io_tree *tree, struct page *page, | 2494 | static 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 | ||
4163 | static void check_buffer_tree_ref(struct extent_buffer *eb) | 4167 | static 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 | ||
4384 | void free_extent_buffer(struct extent_buffer *eb) | 4393 | void 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)) |