From: Christoph Hellwig <hch@lst.de>
To: Chris Mason <clm@fb.com>, Josef Bacik <josef@toxicpanda.com>,
David Sterba <dsterba@suse.com>
Cc: Nikolay Borisov <nborisov@suse.com>,
Johannes Thumshirn <johannes.thumshirn@wdc.com>,
linux-btrfs@vger.kernel.org
Subject: [PATCH 05/11] btrfs: remove bioc->stripes_pending
Date: Wed, 13 Jul 2022 08:13:53 +0200 [thread overview]
Message-ID: <20220713061359.1980118-6-hch@lst.de> (raw)
In-Reply-To: <20220713061359.1980118-1-hch@lst.de>
The stripes_pending in the btrfs_io_context counts number of inflight
low-level bios for an upper btrfs_bio. For reads this is generally
one as reads are never cloned, while for writes we can trivially use
the bio remaining mechanisms that is used for chained bios.
To be able to make use of that mechanism, split out a separate trivial
end_io handler for the cloned bios that does a minimal amount of error
tracking and which then calls bio_endio on the original bio to transfer
control to that, with the remaining counter making sure it is completed
last. This then allows to merge btrfs_end_bioc into the original bio
bi_end_io handler. To make this all work all error handling needs to
happen through the bi_end_io handler, which requires a small amount
of reshuffling in submit_stripe_bio so that the bio is cloned already
by the time the suitability of the device is checked.
This reduces the size of the btrfs_io_context and prepares splitting
the btrfs_bio at the stripe boundary.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/btrfs/volumes.c | 94 ++++++++++++++++++++++++----------------------
fs/btrfs/volumes.h | 1 -
2 files changed, 50 insertions(+), 45 deletions(-)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 3f5672b362202..92e15e523451a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5893,7 +5893,6 @@ static struct btrfs_io_context *alloc_btrfs_io_context(struct btrfs_fs_info *fs_
sizeof(u64) * (total_stripes),
GFP_NOFS|__GFP_NOFAIL);
- atomic_set(&bioc->error, 0);
refcount_set(&bioc->refs, 1);
bioc->fs_info = fs_info;
@@ -6650,7 +6649,21 @@ struct bio *btrfs_bio_clone_partial(struct bio *orig, u64 offset, u64 size)
bio_trim(bio, offset >> 9, size >> 9);
bbio->iter = bio->bi_iter;
return bio;
+}
+
+static void btrfs_log_dev_io_error(struct bio *bio, struct btrfs_device *dev)
+{
+ if (!dev || !dev->bdev)
+ return;
+ if (bio->bi_status != BLK_STS_IOERR && bio->bi_status != BLK_STS_TARGET)
+ return;
+ if (btrfs_op(bio) == BTRFS_MAP_WRITE)
+ btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
+ if (!(bio->bi_opf & REQ_RAHEAD))
+ btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_READ_ERRS);
+ if (bio->bi_opf & REQ_PREFLUSH)
+ btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_FLUSH_ERRS);
}
static struct workqueue_struct *btrfs_end_io_wq(struct btrfs_io_context *bioc)
@@ -6668,62 +6681,54 @@ static void btrfs_end_bio_work(struct work_struct *work)
bio_endio(&bbio->bio);
}
-static void btrfs_end_bioc(struct btrfs_io_context *bioc, bool async)
+static void btrfs_end_bio(struct bio *bio)
{
- struct bio *orig_bio = bioc->orig_bio;
- struct btrfs_bio *bbio = btrfs_bio(orig_bio);
+ struct btrfs_io_stripe *stripe = bio->bi_private;
+ struct btrfs_io_context *bioc = stripe->bioc;
+ struct btrfs_bio *bbio = btrfs_bio(bio);
btrfs_bio_counter_dec(bioc->fs_info);
+ if (bio->bi_status) {
+ atomic_inc(&bioc->error);
+ btrfs_log_dev_io_error(bio, stripe->dev);
+ }
+
bbio->mirror_num = bioc->mirror_num;
- orig_bio->bi_private = bioc->private;
- orig_bio->bi_end_io = bioc->end_io;
+ bio->bi_end_io = bioc->end_io;
+ bio->bi_private = bioc->private;
/*
* Only send an error to the higher layers if it is beyond the tolerance
* threshold.
*/
if (atomic_read(&bioc->error) > bioc->max_errors)
- orig_bio->bi_status = BLK_STS_IOERR;
+ bio->bi_status = BLK_STS_IOERR;
else
- orig_bio->bi_status = BLK_STS_OK;
+ bio->bi_status = BLK_STS_OK;
- if (btrfs_op(orig_bio) == BTRFS_MAP_READ && async) {
+ if (btrfs_op(bio) == BTRFS_MAP_READ) {
INIT_WORK(&bbio->end_io_work, btrfs_end_bio_work);
queue_work(btrfs_end_io_wq(bioc), &bbio->end_io_work);
} else {
- bio_endio(orig_bio);
+ bio_endio(bio);
}
btrfs_put_bioc(bioc);
}
-static void btrfs_end_bio(struct bio *bio)
+static void btrfs_clone_write_end_io(struct bio *bio)
{
struct btrfs_io_stripe *stripe = bio->bi_private;
- struct btrfs_io_context *bioc = stripe->bioc;
if (bio->bi_status) {
- atomic_inc(&bioc->error);
- if (bio->bi_status == BLK_STS_IOERR ||
- bio->bi_status == BLK_STS_TARGET) {
- if (btrfs_op(bio) == BTRFS_MAP_WRITE)
- btrfs_dev_stat_inc_and_print(stripe->dev,
- BTRFS_DEV_STAT_WRITE_ERRS);
- else if (!(bio->bi_opf & REQ_RAHEAD))
- btrfs_dev_stat_inc_and_print(stripe->dev,
- BTRFS_DEV_STAT_READ_ERRS);
- if (bio->bi_opf & REQ_PREFLUSH)
- btrfs_dev_stat_inc_and_print(stripe->dev,
- BTRFS_DEV_STAT_FLUSH_ERRS);
- }
+ atomic_inc(&stripe->bioc->error);
+ btrfs_log_dev_io_error(bio, stripe->dev);
}
- if (bio != bioc->orig_bio)
- bio_put(bio);
-
- if (atomic_dec_and_test(&bioc->stripes_pending))
- btrfs_end_bioc(bioc, true);
+ /* Pass on cotrol to the original bio this one was cloned from */
+ bio_endio(stripe->bioc->orig_bio);
+ bio_put(bio);
}
static void submit_stripe_bio(struct btrfs_io_context *bioc,
@@ -6734,28 +6739,30 @@ static void submit_stripe_bio(struct btrfs_io_context *bioc,
u64 physical = bioc->stripes[dev_nr].physical;
struct bio *bio;
- if (!dev || !dev->bdev ||
- test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) ||
- (btrfs_op(orig_bio) == BTRFS_MAP_WRITE &&
- !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))) {
- atomic_inc(&bioc->error);
- if (atomic_dec_and_test(&bioc->stripes_pending))
- btrfs_end_bioc(bioc, false);
- return;
- }
-
if (clone) {
- bio = bio_alloc_clone(dev->bdev, orig_bio, GFP_NOFS, &fs_bio_set);
+ bio = bio_alloc_clone(NULL, orig_bio, GFP_NOFS, &fs_bio_set);
+ bio_inc_remaining(orig_bio);
+ bio->bi_end_io = btrfs_clone_write_end_io;
} else {
bio = orig_bio;
- bio_set_dev(bio, dev->bdev);
btrfs_bio(bio)->device = dev;
+ bio->bi_end_io = btrfs_end_bio;
}
bioc->stripes[dev_nr].bioc = bioc;
bio->bi_private = &bioc->stripes[dev_nr];
- bio->bi_end_io = btrfs_end_bio;
bio->bi_iter.bi_sector = physical >> 9;
+
+ if (!dev || !dev->bdev ||
+ test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) ||
+ (btrfs_op(bio) == BTRFS_MAP_WRITE &&
+ !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))) {
+ bio_io_error(bio);
+ return;
+ }
+
+ bio_set_dev(bio, dev->bdev);
+
/*
* For zone append writing, bi_sector must point the beginning of the
* zone
@@ -6804,7 +6811,6 @@ void btrfs_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, int mirror
bioc->orig_bio = bio;
bioc->private = bio->bi_private;
bioc->end_io = bio->bi_end_io;
- atomic_set(&bioc->stripes_pending, total_devs);
if ((bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) &&
((btrfs_op(bio) == BTRFS_MAP_WRITE) || (mirror_num > 1))) {
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index bd108c7ed1ac3..9e984a9922c59 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -454,7 +454,6 @@ struct btrfs_discard_stripe {
*/
struct btrfs_io_context {
refcount_t refs;
- atomic_t stripes_pending;
struct btrfs_fs_info *fs_info;
u64 map_type; /* get from map_lookup->type */
bio_end_io_t *end_io;
--
2.30.2
next prev parent reply other threads:[~2022-07-13 6:14 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-13 6:13 btrfs I/O completion cleanup and single device I/O optimizations v2 Christoph Hellwig
2022-07-13 6:13 ` [PATCH 01/11] btrfs: don't call bioset_integrity_create for btrfs_bioset Christoph Hellwig
2022-07-13 6:13 ` [PATCH 02/11] btrfs: move btrfs_bio allocation to volumes.c Christoph Hellwig
2022-07-13 6:13 ` [PATCH 03/11] btrfs: pass the operation to btrfs_bio_alloc Christoph Hellwig
2022-07-13 6:13 ` [PATCH 04/11] btrfs: don't take a bio_counter reference for cloned bios Christoph Hellwig
2022-07-13 6:27 ` Johannes Thumshirn
2022-07-13 6:13 ` Christoph Hellwig [this message]
2022-07-13 6:31 ` [PATCH 05/11] btrfs: remove bioc->stripes_pending Johannes Thumshirn
2022-07-13 6:41 ` Johannes Thumshirn
2022-07-14 12:15 ` Nikolay Borisov
2022-07-13 6:13 ` [PATCH 06/11] btrfs: properly abstract the parity raid bio handling Christoph Hellwig
2022-07-13 6:13 ` [PATCH 07/11] btrfs: give struct btrfs_bio a real end_io handler Christoph Hellwig
2022-07-13 6:47 ` Johannes Thumshirn
2022-07-13 6:51 ` Christoph Hellwig
2022-07-13 6:13 ` [PATCH 08/11] btrfs: split submit_stripe_bio Christoph Hellwig
2022-07-13 6:46 ` Johannes Thumshirn
2022-07-13 6:50 ` Christoph Hellwig
2022-07-13 6:52 ` Johannes Thumshirn
2022-07-14 14:02 ` Nikolay Borisov
2022-07-13 6:13 ` [PATCH 09/11] btrfs: simplify the submit_stripe_bio calling convention Christoph Hellwig
2022-07-13 6:49 ` Johannes Thumshirn
2022-07-14 14:30 ` Nikolay Borisov
2022-07-13 6:13 ` [PATCH 10/11] btrfs: make the btrfs_io_context allocation in __btrfs_map_block optional Christoph Hellwig
2022-07-13 9:58 ` Johannes Thumshirn
2022-07-13 11:18 ` Christoph Hellwig
2022-07-15 8:30 ` Nikolay Borisov
2022-07-13 6:13 ` [PATCH 11/11] btrfs: stop allocation a btrfs_io_context for simple I/O Christoph Hellwig
2022-09-06 13:12 ` btrfs I/O completion cleanup and single device I/O optimizations v2 David Sterba
2022-09-07 9:08 ` Christoph Hellwig
2022-09-09 12:34 ` David Sterba
-- strict thread matches above, loose matches on Subject: below --
2022-08-06 8:03 btrfs I/O completion cleanup and single device I/O optimizations v3 Christoph Hellwig
2022-08-06 8:03 ` [PATCH 05/11] btrfs: remove bioc->stripes_pending Christoph Hellwig
2022-08-18 11:33 ` Anand Jain
2022-08-18 23:36 ` Anand Jain
2022-08-18 23:37 ` Anand Jain
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220713061359.1980118-6-hch@lst.de \
--to=hch@lst.de \
--cc=clm@fb.com \
--cc=dsterba@suse.com \
--cc=johannes.thumshirn@wdc.com \
--cc=josef@toxicpanda.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=nborisov@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).