aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h7
-rw-r--r--fs/btrfs/dev-replace.c4
-rw-r--r--fs/btrfs/raid56.c41
-rw-r--r--fs/btrfs/raid56.h4
-rw-r--r--fs/btrfs/scrub.c2
-rw-r--r--fs/btrfs/volumes.c7
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 */
4098void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info); 4098void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info);
4099void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info); 4099void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info);
4100void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info); 4100void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount);
4101
4102static 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 */
4103struct reada_control { 4108struct 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
923void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info) 923void 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 */
2140int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, 2158int 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;
43struct btrfs_device; 43struct btrfs_device;
44 44
45int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, 45int 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);
48int raid56_parity_write(struct btrfs_root *root, struct bio *bio, 48int 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 }