diff options
| -rw-r--r-- | fs/btrfs/ctree.h | 7 | ||||
| -rw-r--r-- | fs/btrfs/dev-replace.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/raid56.c | 41 | ||||
| -rw-r--r-- | fs/btrfs/raid56.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/scrub.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 7 |
6 files changed, 45 insertions, 20 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index fe69edda11fb..470e3177a7e8 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -4097,7 +4097,12 @@ int btrfs_scrub_progress(struct btrfs_root *root, u64 devid, | |||
| 4097 | /* dev-replace.c */ | 4097 | /* dev-replace.c */ |
| 4098 | void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info); | 4098 | void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info); |
| 4099 | void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info); | 4099 | void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info); |
| 4100 | void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info); | 4100 | void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount); |
| 4101 | |||
| 4102 | static inline void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info) | ||
| 4103 | { | ||
| 4104 | btrfs_bio_counter_sub(fs_info, 1); | ||
| 4105 | } | ||
| 4101 | 4106 | ||
| 4102 | /* reada.c */ | 4107 | /* reada.c */ |
| 4103 | struct reada_control { | 4108 | struct reada_control { |
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 6f662b34ba0e..fa27b4e3b6c8 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c | |||
| @@ -920,9 +920,9 @@ void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info) | |||
| 920 | percpu_counter_inc(&fs_info->bio_counter); | 920 | percpu_counter_inc(&fs_info->bio_counter); |
| 921 | } | 921 | } |
| 922 | 922 | ||
| 923 | void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info) | 923 | void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount) |
| 924 | { | 924 | { |
| 925 | percpu_counter_dec(&fs_info->bio_counter); | 925 | percpu_counter_sub(&fs_info->bio_counter, amount); |
| 926 | 926 | ||
| 927 | if (waitqueue_active(&fs_info->replace_wait)) | 927 | if (waitqueue_active(&fs_info->replace_wait)) |
| 928 | wake_up(&fs_info->replace_wait); | 928 | wake_up(&fs_info->replace_wait); |
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 5ece565bc5f0..8ab2a17bbba8 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c | |||
| @@ -162,6 +162,8 @@ struct btrfs_raid_bio { | |||
| 162 | */ | 162 | */ |
| 163 | int bio_list_bytes; | 163 | int bio_list_bytes; |
| 164 | 164 | ||
| 165 | int generic_bio_cnt; | ||
| 166 | |||
| 165 | atomic_t refs; | 167 | atomic_t refs; |
| 166 | 168 | ||
| 167 | atomic_t stripes_pending; | 169 | atomic_t stripes_pending; |
| @@ -354,6 +356,7 @@ static void merge_rbio(struct btrfs_raid_bio *dest, | |||
| 354 | { | 356 | { |
| 355 | bio_list_merge(&dest->bio_list, &victim->bio_list); | 357 | bio_list_merge(&dest->bio_list, &victim->bio_list); |
| 356 | dest->bio_list_bytes += victim->bio_list_bytes; | 358 | dest->bio_list_bytes += victim->bio_list_bytes; |
| 359 | dest->generic_bio_cnt += victim->generic_bio_cnt; | ||
| 357 | bio_list_init(&victim->bio_list); | 360 | bio_list_init(&victim->bio_list); |
| 358 | } | 361 | } |
| 359 | 362 | ||
| @@ -891,6 +894,10 @@ static void rbio_orig_end_io(struct btrfs_raid_bio *rbio, int err, int uptodate) | |||
| 891 | { | 894 | { |
| 892 | struct bio *cur = bio_list_get(&rbio->bio_list); | 895 | struct bio *cur = bio_list_get(&rbio->bio_list); |
| 893 | struct bio *next; | 896 | struct bio *next; |
| 897 | |||
| 898 | if (rbio->generic_bio_cnt) | ||
| 899 | btrfs_bio_counter_sub(rbio->fs_info, rbio->generic_bio_cnt); | ||
| 900 | |||
| 894 | free_raid_bio(rbio); | 901 | free_raid_bio(rbio); |
| 895 | 902 | ||
| 896 | while (cur) { | 903 | while (cur) { |
| @@ -1775,6 +1782,7 @@ int raid56_parity_write(struct btrfs_root *root, struct bio *bio, | |||
| 1775 | struct btrfs_raid_bio *rbio; | 1782 | struct btrfs_raid_bio *rbio; |
| 1776 | struct btrfs_plug_cb *plug = NULL; | 1783 | struct btrfs_plug_cb *plug = NULL; |
| 1777 | struct blk_plug_cb *cb; | 1784 | struct blk_plug_cb *cb; |
| 1785 | int ret; | ||
| 1778 | 1786 | ||
| 1779 | rbio = alloc_rbio(root, bbio, raid_map, stripe_len); | 1787 | rbio = alloc_rbio(root, bbio, raid_map, stripe_len); |
| 1780 | if (IS_ERR(rbio)) { | 1788 | if (IS_ERR(rbio)) { |
| @@ -1785,12 +1793,19 @@ int raid56_parity_write(struct btrfs_root *root, struct bio *bio, | |||
| 1785 | rbio->bio_list_bytes = bio->bi_iter.bi_size; | 1793 | rbio->bio_list_bytes = bio->bi_iter.bi_size; |
| 1786 | rbio->operation = BTRFS_RBIO_WRITE; | 1794 | rbio->operation = BTRFS_RBIO_WRITE; |
| 1787 | 1795 | ||
| 1796 | btrfs_bio_counter_inc_noblocked(root->fs_info); | ||
| 1797 | rbio->generic_bio_cnt = 1; | ||
| 1798 | |||
| 1788 | /* | 1799 | /* |
| 1789 | * don't plug on full rbios, just get them out the door | 1800 | * don't plug on full rbios, just get them out the door |
| 1790 | * as quickly as we can | 1801 | * as quickly as we can |
| 1791 | */ | 1802 | */ |
| 1792 | if (rbio_is_full(rbio)) | 1803 | if (rbio_is_full(rbio)) { |
| 1793 | return full_stripe_write(rbio); | 1804 | ret = full_stripe_write(rbio); |
| 1805 | if (ret) | ||
| 1806 | btrfs_bio_counter_dec(root->fs_info); | ||
| 1807 | return ret; | ||
| 1808 | } | ||
| 1794 | 1809 | ||
| 1795 | cb = blk_check_plugged(btrfs_raid_unplug, root->fs_info, | 1810 | cb = blk_check_plugged(btrfs_raid_unplug, root->fs_info, |
| 1796 | sizeof(*plug)); | 1811 | sizeof(*plug)); |
| @@ -1801,10 +1816,13 @@ int raid56_parity_write(struct btrfs_root *root, struct bio *bio, | |||
| 1801 | INIT_LIST_HEAD(&plug->rbio_list); | 1816 | INIT_LIST_HEAD(&plug->rbio_list); |
| 1802 | } | 1817 | } |
| 1803 | list_add_tail(&rbio->plug_list, &plug->rbio_list); | 1818 | list_add_tail(&rbio->plug_list, &plug->rbio_list); |
| 1819 | ret = 0; | ||
| 1804 | } else { | 1820 | } else { |
| 1805 | return __raid56_parity_write(rbio); | 1821 | ret = __raid56_parity_write(rbio); |
| 1822 | if (ret) | ||
| 1823 | btrfs_bio_counter_dec(root->fs_info); | ||
| 1806 | } | 1824 | } |
| 1807 | return 0; | 1825 | return ret; |
| 1808 | } | 1826 | } |
| 1809 | 1827 | ||
| 1810 | /* | 1828 | /* |
| @@ -2139,19 +2157,17 @@ cleanup: | |||
| 2139 | */ | 2157 | */ |
| 2140 | int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, | 2158 | int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, |
| 2141 | struct btrfs_bio *bbio, u64 *raid_map, | 2159 | struct btrfs_bio *bbio, u64 *raid_map, |
| 2142 | u64 stripe_len, int mirror_num, int hold_bbio) | 2160 | u64 stripe_len, int mirror_num, int generic_io) |
| 2143 | { | 2161 | { |
| 2144 | struct btrfs_raid_bio *rbio; | 2162 | struct btrfs_raid_bio *rbio; |
| 2145 | int ret; | 2163 | int ret; |
| 2146 | 2164 | ||
| 2147 | rbio = alloc_rbio(root, bbio, raid_map, stripe_len); | 2165 | rbio = alloc_rbio(root, bbio, raid_map, stripe_len); |
| 2148 | if (IS_ERR(rbio)) { | 2166 | if (IS_ERR(rbio)) { |
| 2149 | __free_bbio_and_raid_map(bbio, raid_map, !hold_bbio); | 2167 | __free_bbio_and_raid_map(bbio, raid_map, generic_io); |
| 2150 | return PTR_ERR(rbio); | 2168 | return PTR_ERR(rbio); |
| 2151 | } | 2169 | } |
| 2152 | 2170 | ||
| 2153 | if (hold_bbio) | ||
| 2154 | set_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags); | ||
| 2155 | rbio->operation = BTRFS_RBIO_READ_REBUILD; | 2171 | rbio->operation = BTRFS_RBIO_READ_REBUILD; |
| 2156 | bio_list_add(&rbio->bio_list, bio); | 2172 | bio_list_add(&rbio->bio_list, bio); |
| 2157 | rbio->bio_list_bytes = bio->bi_iter.bi_size; | 2173 | rbio->bio_list_bytes = bio->bi_iter.bi_size; |
| @@ -2159,11 +2175,18 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, | |||
| 2159 | rbio->faila = find_logical_bio_stripe(rbio, bio); | 2175 | rbio->faila = find_logical_bio_stripe(rbio, bio); |
| 2160 | if (rbio->faila == -1) { | 2176 | if (rbio->faila == -1) { |
| 2161 | BUG(); | 2177 | BUG(); |
| 2162 | __free_bbio_and_raid_map(bbio, raid_map, !hold_bbio); | 2178 | __free_bbio_and_raid_map(bbio, raid_map, generic_io); |
| 2163 | kfree(rbio); | 2179 | kfree(rbio); |
| 2164 | return -EIO; | 2180 | return -EIO; |
| 2165 | } | 2181 | } |
| 2166 | 2182 | ||
| 2183 | if (generic_io) { | ||
| 2184 | btrfs_bio_counter_inc_noblocked(root->fs_info); | ||
| 2185 | rbio->generic_bio_cnt = 1; | ||
| 2186 | } else { | ||
| 2187 | set_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags); | ||
| 2188 | } | ||
| 2189 | |||
| 2167 | /* | 2190 | /* |
| 2168 | * reconstruct from the q stripe if they are | 2191 | * reconstruct from the q stripe if they are |
| 2169 | * asking for mirror 3 | 2192 | * asking for mirror 3 |
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h index 3d4ddb3d861d..31d4a157b5e3 100644 --- a/fs/btrfs/raid56.h +++ b/fs/btrfs/raid56.h | |||
| @@ -43,8 +43,8 @@ struct btrfs_raid_bio; | |||
| 43 | struct btrfs_device; | 43 | struct btrfs_device; |
| 44 | 44 | ||
| 45 | int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, | 45 | int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, |
| 46 | struct btrfs_bio *bbio, u64 *raid_map, | 46 | struct btrfs_bio *bbio, u64 *raid_map, |
| 47 | u64 stripe_len, int mirror_num, int hold_bbio); | 47 | u64 stripe_len, int mirror_num, int generic_io); |
| 48 | int raid56_parity_write(struct btrfs_root *root, struct bio *bio, | 48 | int raid56_parity_write(struct btrfs_root *root, struct bio *bio, |
| 49 | struct btrfs_bio *bbio, u64 *raid_map, | 49 | struct btrfs_bio *bbio, u64 *raid_map, |
| 50 | u64 stripe_len); | 50 | u64 stripe_len); |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 0ae837fd676d..27f2e16cd259 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
| @@ -1477,7 +1477,7 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info, | |||
| 1477 | ret = raid56_parity_recover(fs_info->fs_root, bio, page->recover->bbio, | 1477 | ret = raid56_parity_recover(fs_info->fs_root, bio, page->recover->bbio, |
| 1478 | page->recover->raid_map, | 1478 | page->recover->raid_map, |
| 1479 | page->recover->map_length, | 1479 | page->recover->map_length, |
| 1480 | page->mirror_num, 1); | 1480 | page->mirror_num, 0); |
| 1481 | if (ret) | 1481 | if (ret) |
| 1482 | return ret; | 1482 | return ret; |
| 1483 | 1483 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 6d8a5e8d8c39..cbb766577f31 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -5843,12 +5843,9 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, | |||
| 5843 | } else { | 5843 | } else { |
| 5844 | ret = raid56_parity_recover(root, bio, bbio, | 5844 | ret = raid56_parity_recover(root, bio, bbio, |
| 5845 | raid_map, map_length, | 5845 | raid_map, map_length, |
| 5846 | mirror_num, 0); | 5846 | mirror_num, 1); |
| 5847 | } | 5847 | } |
| 5848 | /* | 5848 | |
| 5849 | * FIXME, replace dosen't support raid56 yet, please fix | ||
| 5850 | * it in the future. | ||
| 5851 | */ | ||
| 5852 | btrfs_bio_counter_dec(root->fs_info); | 5849 | btrfs_bio_counter_dec(root->fs_info); |
| 5853 | return ret; | 5850 | return ret; |
| 5854 | } | 5851 | } |
