From: Mike Snitzer <snitzer@redhat.com>
To: Mikulas Patocka <mpatocka@redhat.com>
Cc: dm-devel@redhat.com
Subject: Re: [PATCH v2 5/9] dm: improve noclone bio support
Date: Fri, 22 Feb 2019 11:56:54 -0500 [thread overview]
Message-ID: <20190222165653.GA9619@redhat.com> (raw)
In-Reply-To: <20190222152210.GA9341@redhat.com>
On Fri, Feb 22 2019 at 10:22am -0500,
Mike Snitzer <snitzer@redhat.com> wrote:
> On Fri, Feb 22 2019 at 5:59am -0500,
> Mikulas Patocka <mpatocka@redhat.com> wrote:
>
> > Hi
> >
> > I've fonud out that this patch causes timeout in the lvm test
> > shell/activate-missing-segment.sh and some others.
>
> OK, I can reproduce with:
> make check_local T=shell/activate-missing-segment.sh
>
> Interestingly, it isn't hung in kernel, test can be interrupted.
> And it is hanging at shell/activate-missing-segment.sh's : aux disable_dev "$dev1"
>
> Other tests with "aux disable_dev" hang too
> (e.g. shell/lvcreate-repair.sh, shell/vgreduce-usage.sh)
>
> continued below:
>
> > On Wed, 20 Feb 2019, Mike Snitzer wrote:
> >
> > > Leverage fact that dm_queue_split() enables use of noclone support even
> > > for targets that require additional splitting (via ti->max_io_len).
> > >
> > > To achieve this move noclone processing from dm_make_request() to
> > > dm_process_bio() and check if bio->bi_end_io is already set to
> > > noclone_endio. This also fixes dm_wq_work() to be able to support
> > > noclone bios (because it calls dm_process_bio()).
> > >
> > > While at it, clean up ->map() return processing to be comparable to
> > > __map_bio() and add some code comments that explain why certain
> > > conditionals exist to prevent the use of noclone.
> > >
> > > Signed-off-by: Mike Snitzer <snitzer@redhat.com>
> > > ---
> > > drivers/md/dm.c | 103 ++++++++++++++++++++++++++++++++++----------------------
> > > 1 file changed, 62 insertions(+), 41 deletions(-)
> > >
> > > diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> > > index 57919f211acc..d84735be6927 100644
> > > --- a/drivers/md/dm.c
> > > +++ b/drivers/md/dm.c
> > > @@ -1764,14 +1764,75 @@ static blk_qc_t dm_process_bio(struct mapped_device *md,
> > > * If in ->make_request_fn we need to use blk_queue_split(), otherwise
> > > * queue_limits for abnormal requests (e.g. discard, writesame, etc)
> > > * won't be imposed.
> > > + *
> > > + * For normal READ and WRITE requests we benefit from upfront splitting
> > > + * via dm_queue_split() because we can then leverage noclone support below.
> > > */
> > > - if (current->bio_list) {
> > > + if (current->bio_list && (bio->bi_end_io != noclone_endio)) {
> > > + /*
> > > + * It is fine to use {blk,dm}_queue_split() before opting to use noclone
> > > + * because any ->bi_private and ->bi_end_io will get saved off below.
> > > + * Once noclone_endio() is called the bio_chain's endio will kick in.
> > > + * - __split_and_process_bio() can split further, but any targets that
> > > + * require late _DM_ initiated splitting (e.g. dm_accept_partial_bio()
> > > + * callers) shouldn't set ti->no_clone.
> > > + */
> > > if (is_abnormal_io(bio))
> > > blk_queue_split(md->queue, &bio);
> > > else
> > > dm_queue_split(md, ti, &bio);
> > > }
> > >
> > > + if (dm_table_supports_noclone(map) &&
> > > + (bio_op(bio) == REQ_OP_READ || bio_op(bio) == REQ_OP_WRITE) &&
> > > + likely(!(bio->bi_opf & REQ_PREFLUSH)) &&
> > > + likely(!bio_integrity(bio)) && /* integrity requires specialized processing */
> > > + likely(!dm_stats_used(&md->stats))) { /* noclone doesn't support dm-stats */
> > > + int r;
> > > + struct dm_noclone *noclone;
> > > +
> > > + /* Already been here if bio->bi_end_io is noclone_endio, reentered via dm_wq_work() */
> > > + if (bio->bi_end_io != noclone_endio) {
>
> This conditional is causing it ^
>
> Very strange...
Added some debugging:
Feb 22 10:46:28 thegoat kernel: device-mapper: core: dm_process_bio: 253:2: bio=00000000c70f3c09 bio->bi_iter.bi_sector=0 len=256 bio->bi_end_io != noclone_endio
Feb 22 10:46:28 thegoat kernel: device-mapper: core: dm_process_bio: 253:0: bio=00000000c70f3c09 bio->bi_iter.bi_sector=2048 len=256 bio->bi_end_io = noclone_endio
...
Feb 22 10:46:28 thegoat kernel: device-mapper: core: dm_process_bio: 253:2: bio=00000000da9cadf3 bio->bi_iter.bi_sector=0 len=256 bio->bi_end_io != noclone_endio
Feb 22 10:46:28 thegoat kernel: device-mapper: core: dm_process_bio: 253:0: bio=00000000da9cadf3 bio->bi_iter.bi_sector=2048 len=256 bio->bi_end_io = noclone_endio
So the same noclone bio is entering devices in the stacked DM device
(perfectly normal).
This fixes the issue:
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index a9856f1986df..8fbe4d5ec8e4 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1831,15 +1831,16 @@ static blk_qc_t dm_process_bio(struct mapped_device *md,
likely(!bio_integrity(bio)) && /* integrity requires specialized processing */
likely(!dm_stats_used(&md->stats))) { /* noclone doesn't support dm-stats */
int r;
- struct dm_noclone *noclone;
-
- /* Already been here if bio->bi_end_io is noclone_endio, reentered via dm_wq_work() */
- if (bio->bi_end_io != noclone_endio) {
+ /*
+ * Only allocate noclone if in ->make_request_fn, otherwise
+ * leak could occur due to reentering (e.g. from dm_wq_work)
+ */
+ if (current->bio_list) {
+ struct dm_noclone *noclone;
noclone = kmalloc_node(sizeof(*noclone) + ti->per_io_data_size + sizeof(unsigned),
GFP_NOWAIT, md->numa_node_id);
if (unlikely(!noclone))
goto no_fast_path;
-
noclone->md = md;
noclone->start_time = jiffies;
noclone->orig_bi_end_io = bio->bi_end_io;
That said, I've reasoned through other edge cases that need to be dealt
with and will layer other fixes in addition to this one.
next prev parent reply other threads:[~2019-02-22 16:56 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-20 21:44 [PATCH v2 0/9] dm: changes staged in linux-next for 5.1 so far Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 1/9] dm: update dm_process_bio() to split bio if in ->make_request_fn() Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 2/9] dm: eliminate 'split_discard_bios' flag from DM target interface Mike Snitzer
2019-02-21 4:36 ` Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 3/9] dm: refactor start_io_acct and end_io_acct Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 4/9] dm: implement noclone optimization for bio-based Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 5/9] dm: improve noclone bio support Mike Snitzer
2019-02-22 10:59 ` Mikulas Patocka
2019-02-22 15:22 ` Mike Snitzer
2019-02-22 16:56 ` Mike Snitzer [this message]
2019-02-20 21:44 ` [PATCH v2 6/9] dm: add per-bio-data support to noclone bio Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 7/9] dm: improve noclone_endio() to support multipath target Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 8/9] dm mpath: enable noclone support for bio-based Mike Snitzer
2019-02-20 21:44 ` [PATCH v2 9/9] dm: remove unused _rq_tio_cache and _rq_cache Mike Snitzer
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=20190222165653.GA9619@redhat.com \
--to=snitzer@redhat.com \
--cc=dm-devel@redhat.com \
--cc=mpatocka@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.