Skip to content

Commit 7836dbb

Browse files
adam900710kdave
authored andcommitted
btrfs: make sure all btrfs_bio::end_io is called in task context
[BACKGROUND] Btrfs has a lot of different bi_end_io functions, to handle different raid profiles. But they introduced a lot of different context for btrfs_bio::end_io() calls: - Simple read bios Run in task context, backed by either endio_meta_workers or endio_workers. - Simple write bios Run in irq context. - RAID56 write or rebuild bios Run in task context, backed by rmw_workers. - Mirrored write bios Run in irq context. This is very inconsistent, and contributes to the huge amount of workqueues used in btrfs. [ENHANCEMENT] Make all above bios to call their btrfs_bio::end_io() in task context, backed by either endio_meta_workers for metadata, or endio_workers for data. For simple write bios, merge the handling into simple_end_io_work(). For mirrored write bios, it will be a little more complex, since both the original or the cloned bios can run the final btrfs_bio::end_io(). Here we make sure the cloned bios are using btrfs_bioset, to reuse the end_io_work, and run both original and cloned work inside the workqueue. And add extra ASSERT()s to make sure btrfs_bio_end_io() is running in task context. This not only unifies the context for btrfs_bio::end_io() functions, but also opens a new door for further btrfs_bio::end_io() related cleanups. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent b61fb56 commit 7836dbb

File tree

1 file changed

+46
-18
lines changed

1 file changed

+46
-18
lines changed

fs/btrfs/bio.c

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ static struct btrfs_bio *btrfs_split_bio(struct btrfs_fs_info *fs_info,
102102

103103
void btrfs_bio_end_io(struct btrfs_bio *bbio, blk_status_t status)
104104
{
105+
/* Make sure we're already in task context. */
106+
ASSERT(in_task());
107+
105108
bbio->bio.bi_status = status;
106109
if (bbio->bio.bi_pool == &btrfs_clone_bioset) {
107110
struct btrfs_bio *orig_bbio = bbio->private;
@@ -318,15 +321,20 @@ static struct workqueue_struct *btrfs_end_io_wq(const struct btrfs_fs_info *fs_i
318321
return fs_info->endio_workers;
319322
}
320323

321-
static void btrfs_end_bio_work(struct work_struct *work)
324+
static void simple_end_io_work(struct work_struct *work)
322325
{
323326
struct btrfs_bio *bbio = container_of(work, struct btrfs_bio, end_io_work);
327+
struct bio *bio = &bbio->bio;
324328

325-
/* Metadata reads are checked and repaired by the submitter. */
326-
if (is_data_bbio(bbio))
327-
btrfs_check_read_bio(bbio, bbio->bio.bi_private);
328-
else
329-
btrfs_bio_end_io(bbio, bbio->bio.bi_status);
329+
if (bio_op(bio) == REQ_OP_READ) {
330+
/* Metadata reads are checked and repaired by the submitter. */
331+
if (is_data_bbio(bbio))
332+
return btrfs_check_read_bio(bbio, bbio->bio.bi_private);
333+
return btrfs_bio_end_io(bbio, bbio->bio.bi_status);
334+
}
335+
if (bio_is_zone_append(bio) && !bio->bi_status)
336+
btrfs_record_physical_zoned(bbio);
337+
btrfs_bio_end_io(bbio, bbio->bio.bi_status);
330338
}
331339

332340
static void btrfs_simple_end_io(struct bio *bio)
@@ -340,21 +348,18 @@ static void btrfs_simple_end_io(struct bio *bio)
340348
if (bio->bi_status)
341349
btrfs_log_dev_io_error(bio, dev);
342350

343-
if (bio_op(bio) == REQ_OP_READ) {
344-
INIT_WORK(&bbio->end_io_work, btrfs_end_bio_work);
345-
queue_work(btrfs_end_io_wq(fs_info, bio), &bbio->end_io_work);
346-
} else {
347-
if (bio_is_zone_append(bio) && !bio->bi_status)
348-
btrfs_record_physical_zoned(bbio);
349-
btrfs_bio_end_io(bbio, bbio->bio.bi_status);
350-
}
351+
INIT_WORK(&bbio->end_io_work, simple_end_io_work);
352+
queue_work(btrfs_end_io_wq(fs_info, bio), &bbio->end_io_work);
351353
}
352354

353355
static void btrfs_raid56_end_io(struct bio *bio)
354356
{
355357
struct btrfs_io_context *bioc = bio->bi_private;
356358
struct btrfs_bio *bbio = btrfs_bio(bio);
357359

360+
/* RAID56 endio is always handled in workqueue. */
361+
ASSERT(in_task());
362+
358363
btrfs_bio_counter_dec(bioc->fs_info);
359364
bbio->mirror_num = bioc->mirror_num;
360365
if (bio_op(bio) == REQ_OP_READ && is_data_bbio(bbio))
@@ -365,11 +370,12 @@ static void btrfs_raid56_end_io(struct bio *bio)
365370
btrfs_put_bioc(bioc);
366371
}
367372

368-
static void btrfs_orig_write_end_io(struct bio *bio)
373+
static void orig_write_end_io_work(struct work_struct *work)
369374
{
375+
struct btrfs_bio *bbio = container_of(work, struct btrfs_bio, end_io_work);
376+
struct bio *bio = &bbio->bio;
370377
struct btrfs_io_stripe *stripe = bio->bi_private;
371378
struct btrfs_io_context *bioc = stripe->bioc;
372-
struct btrfs_bio *bbio = btrfs_bio(bio);
373379

374380
btrfs_bio_counter_dec(bioc->fs_info);
375381

@@ -394,8 +400,18 @@ static void btrfs_orig_write_end_io(struct bio *bio)
394400
btrfs_put_bioc(bioc);
395401
}
396402

397-
static void btrfs_clone_write_end_io(struct bio *bio)
403+
static void btrfs_orig_write_end_io(struct bio *bio)
404+
{
405+
struct btrfs_bio *bbio = btrfs_bio(bio);
406+
407+
INIT_WORK(&bbio->end_io_work, orig_write_end_io_work);
408+
queue_work(btrfs_end_io_wq(bbio->inode->root->fs_info, bio), &bbio->end_io_work);
409+
}
410+
411+
static void clone_write_end_io_work(struct work_struct *work)
398412
{
413+
struct btrfs_bio *bbio = container_of(work, struct btrfs_bio, end_io_work);
414+
struct bio *bio = &bbio->bio;
399415
struct btrfs_io_stripe *stripe = bio->bi_private;
400416

401417
if (bio->bi_status) {
@@ -410,6 +426,14 @@ static void btrfs_clone_write_end_io(struct bio *bio)
410426
bio_put(bio);
411427
}
412428

429+
static void btrfs_clone_write_end_io(struct bio *bio)
430+
{
431+
struct btrfs_bio *bbio = btrfs_bio(bio);
432+
433+
INIT_WORK(&bbio->end_io_work, clone_write_end_io_work);
434+
queue_work(btrfs_end_io_wq(bbio->inode->root->fs_info, bio), &bbio->end_io_work);
435+
}
436+
413437
static void btrfs_submit_dev_bio(struct btrfs_device *dev, struct bio *bio)
414438
{
415439
if (!dev || !dev->bdev ||
@@ -456,6 +480,7 @@ static void btrfs_submit_dev_bio(struct btrfs_device *dev, struct bio *bio)
456480
static void btrfs_submit_mirrored_bio(struct btrfs_io_context *bioc, int dev_nr)
457481
{
458482
struct bio *orig_bio = bioc->orig_bio, *bio;
483+
struct btrfs_bio *orig_bbio = btrfs_bio(orig_bio);
459484

460485
ASSERT(bio_op(orig_bio) != REQ_OP_READ);
461486

@@ -464,8 +489,11 @@ static void btrfs_submit_mirrored_bio(struct btrfs_io_context *bioc, int dev_nr)
464489
bio = orig_bio;
465490
bio->bi_end_io = btrfs_orig_write_end_io;
466491
} else {
467-
bio = bio_alloc_clone(NULL, orig_bio, GFP_NOFS, &fs_bio_set);
492+
/* We need to use endio_work to run end_io in task context. */
493+
bio = bio_alloc_clone(NULL, orig_bio, GFP_NOFS, &btrfs_bioset);
468494
bio_inc_remaining(orig_bio);
495+
btrfs_bio_init(btrfs_bio(bio), orig_bbio->inode,
496+
orig_bbio->file_offset, NULL, NULL);
469497
bio->bi_end_io = btrfs_clone_write_end_io;
470498
}
471499

0 commit comments

Comments
 (0)