aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2022-08-06 10:03:25 +0200
committerDavid Sterba <dsterba@suse.com>2022-09-26 12:27:59 +0200
commitf1c2937976be6cc2e4d5b322702fbba5833524cb (patch)
tree3c1f4d259225e169d70913824234fcfd1aeb41e5 /fs/btrfs/volumes.c
parentbtrfs: use chained bios when cloning (diff)
downloadwireguard-linux-f1c2937976be6cc2e4d5b322702fbba5833524cb.tar.xz
wireguard-linux-f1c2937976be6cc2e4d5b322702fbba5833524cb.zip
btrfs: properly abstract the parity raid bio handling
The parity raid write/recover functionality is currently not very well abstracted from the bio submission and completion handling in volumes.c: - the raid56 code directly completes the original btrfs_bio fed into btrfs_submit_bio instead of dispatching back to volumes.c - the raid56 code consumes the bioc and bio_counter references taken by volumes.c, which also leads to special casing of the calls from the scrub code into the raid56 code To fix this up supply a bi_end_io handler that calls back into the volumes.c machinery, which then puts the bioc, decrements the bio_counter and completes the original bio, and updates the scrub code to also take ownership of the bioc and bio_counter in all cases. Reviewed-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: Anand Jain <anand.jain@oracle.com> Tested-by: Nikolay Borisov <nborisov@suse.com> Tested-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 44c7529c70c3..112547d6d5d4 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6684,6 +6684,20 @@ static void btrfs_end_bio_work(struct work_struct *work)
bio_endio(&bbio->bio);
}
+static void btrfs_raid56_end_io(struct bio *bio)
+{
+ struct btrfs_io_context *bioc = bio->bi_private;
+ struct btrfs_bio *bbio = btrfs_bio(bio);
+
+ btrfs_bio_counter_dec(bioc->fs_info);
+ bbio->mirror_num = bioc->mirror_num;
+ bio->bi_end_io = bioc->end_io;
+ bio->bi_private = bioc->private;
+ bio->bi_end_io(bio);
+
+ btrfs_put_bioc(bioc);
+}
+
static void btrfs_end_bio(struct bio *bio)
{
struct btrfs_io_stripe *stripe = bio->bi_private;
@@ -6817,10 +6831,12 @@ void btrfs_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, int mirror
if ((bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) &&
((btrfs_op(bio) == BTRFS_MAP_WRITE) || (mirror_num > 1))) {
+ bio->bi_private = bioc;
+ bio->bi_end_io = btrfs_raid56_end_io;
if (btrfs_op(bio) == BTRFS_MAP_WRITE)
raid56_parity_write(bio, bioc);
else
- raid56_parity_recover(bio, bioc, mirror_num, true);
+ raid56_parity_recover(bio, bioc, mirror_num);
return;
}