From: Mike Snitzer <snitzer@kernel.org>
To: Ignat Korchagin <ignat@cloudflare.com>, Hou Tao <houtao@huaweicloud.com>
Cc: dm-devel@redhat.com, mpatocka@redhat.com,
linux-kernel@vger.kernel.org, Alasdair Kergon <agk@redhat.com>,
houtao1@huawei.com
Subject: Re: [dm-devel] dm crypt: initialize tasklet in crypt_io_init()
Date: Wed, 8 Mar 2023 14:19:23 -0500 [thread overview]
Message-ID: <ZAjfu0R7rv45J3Dr@redhat.com> (raw)
In-Reply-To: <CALrw=nFrbWF2ZhQtK9gx5ZFHK4Cd9outwEQqByJgmb7ryOoCgA@mail.gmail.com>
On Wed, Mar 08 2023 at 8:55P -0500,
Ignat Korchagin <ignat@cloudflare.com> wrote:
> On Wed, Mar 8, 2023 at 2:56 AM Hou Tao <houtao@huaweicloud.com> wrote:
> >
> > Hi,
> >
> > On 3/7/2023 10:47 PM, Mike Snitzer wrote:
> > > On Mon, Mar 06 2023 at 9:12P -0500,
> > > Hou Tao <houtao@huaweicloud.com> wrote:
> > >
> > >> Hi,
> > >>
> > >> On 3/7/2023 3:31 AM, Mike Snitzer wrote:
> > >>> On Mon, Mar 06 2023 at 8:49P -0500,
> > >>> Hou Tao <houtao@huaweicloud.com> wrote:
> > >>>
> > >>>> From: Hou Tao <houtao1@huawei.com>
> > >>>>
> > >>>> When neither no_read_workqueue nor no_write_workqueue are enabled,
> > >>>> tasklet_trylock() in crypt_dec_pending() may still return false due to
> > >>>> an uninitialized state, and dm-crypt will do io completion in io_queue
> > >>>> instead of current context unnecessarily.
> > >>> Have you actually experienced this?
> > >> Yes. I had written a bpftrace script to check the completion context of
> > >> blkdev_bio_end_io_simple() when doing direct io read on dm-crypt device. The
> > >> expected context should be unbound workers of crypt_queue, but sometimes the
> > >> context is the bound worker of io_queue.
> > > OK, thanks for clarifying. Curious to know the circumstance (I
> > > thought per-bio-data is zero'd -- but it may be I'm mistaken).
> > The circumstance is just a normal qemu VM running the vanilla kernel for test
> > purpose. According to the implementation of bio_alloc_bioset(), the front pad of
> > bio is not initialized and only bio itself is initialized. AFAIK if
> > CONFIG_INIT_ON_ALLOC_DEFAULT_ON is enabled, per-bio-data may be zeroed.
OK.
> > > From: Mike Snitzer <snitzer@kernel.org>
> > > Date: Mon, 6 Mar 2023 15:58:33 -0500
> > > Subject: [PATCH] dm crypt: conditionally enable code needed for tasklet usecases
> > >
> > > Use jump_label to limit the need for branching, and tasklet_init(),
> > > unless either of the optional "no_read_workqueue" and/or
> > > "no_write_workqueue" features are used.
> > >
> > > Signed-off-by: Mike Snitzer <snitzer@kernel.org>
> > > ---
> > > drivers/md/dm-crypt.c | 35 +++++++++++++++++++++++++++--------
> > > 1 file changed, 27 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> > > index 641457e72603..2d0309ca07f5 100644
> > > --- a/drivers/md/dm-crypt.c
> > > +++ b/drivers/md/dm-crypt.c
> > > @@ -40,6 +40,7 @@
> > > #include <keys/user-type.h>
> > > #include <keys/encrypted-type.h>
> > > #include <keys/trusted-type.h>
> > > +#include <linux/jump_label.h>
> > >
> > > #include <linux/device-mapper.h>
> > >
> > > @@ -85,6 +86,8 @@ struct dm_crypt_io {
> > > struct rb_node rb_node;
> > > } CRYPTO_MINALIGN_ATTR;
> > >
> > > +static DEFINE_STATIC_KEY_FALSE(use_tasklet_enabled);
> > > +
> > > struct dm_crypt_request {
> > > struct convert_context *ctx;
> > > struct scatterlist sg_in[4];
> > > @@ -1730,12 +1733,15 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc,
> > > io->sector = sector;
> > > io->error = 0;
> > > io->ctx.r.req = NULL;
> > > - /*
> > > - * tasklet_init() here to ensure crypt_dec_pending()'s
> > > - * tasklet_trylock() doesn't incorrectly return false
> > > - * even when tasklet isn't in use.
> > > - */
> > > - tasklet_init(&io->tasklet, kcryptd_crypt_tasklet, (unsigned long)&io->work);
> > > + if (static_branch_unlikely(&use_tasklet_enabled)) {
> > > + /*
> > > + * tasklet_init() here to ensure crypt_dec_pending()'s
> > > + * tasklet_trylock() doesn't incorrectly return false
> > > + * even when tasklet isn't in use.
> > > + */
> > > + tasklet_init(&io->tasklet, kcryptd_crypt_tasklet,
> > > + (unsigned long)&io->work);
> > > + }
> > > io->integrity_metadata = NULL;
> > > io->integrity_metadata_from_pool = false;
> > > atomic_set(&io->io_pending, 0);
> > > @@ -1775,6 +1781,10 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
> > > kfree(io->integrity_metadata);
> > >
> > > base_bio->bi_status = error;
> > > + if (!static_branch_unlikely(&use_tasklet_enabled)) {
> > > + bio_endio(base_bio);
> > > + return;
> > > + }
> > Because use_tasklet_enabled can be enabled concurrently, so I think it is still
> > possible that crypt_dec_pending will try-lock an unitialized tasklet if
> > use_tasklet_enabled is enabled when invoking crypt_dec_pending().
Good point, while I think it is probably acceptable given the worst
case is punting the bio_endio to a workqueue for a time ...
> Perhaps instead we can just pass an additional flag from
> tasklet_schedule to indicate to the function that we're running in a
> tasklet. I originally have chosen the tasklet_trylock/unlock hack to
> avoid passing an extra flag. But unitialized memory makes sense as
> well as the desire to avoid calling tasklet_init unconditionally. So
> an extra member in dm_crypt_io might be the most straightforward here.
... I think we should certainly evaluate the use of an extra flag.
Ignat: I'll have a look at implementing it but if you have a patch
already developed please do share.
Thanks,
Mike
--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel
WARNING: multiple messages have this Message-ID (diff)
From: Mike Snitzer <snitzer@kernel.org>
To: Ignat Korchagin <ignat@cloudflare.com>, Hou Tao <houtao@huaweicloud.com>
Cc: linux-kernel@vger.kernel.org, dm-devel@redhat.com,
mpatocka@redhat.com, houtao1@huawei.com,
Alasdair Kergon <agk@redhat.com>
Subject: Re: dm crypt: initialize tasklet in crypt_io_init()
Date: Wed, 8 Mar 2023 14:19:23 -0500 [thread overview]
Message-ID: <ZAjfu0R7rv45J3Dr@redhat.com> (raw)
In-Reply-To: <CALrw=nFrbWF2ZhQtK9gx5ZFHK4Cd9outwEQqByJgmb7ryOoCgA@mail.gmail.com>
On Wed, Mar 08 2023 at 8:55P -0500,
Ignat Korchagin <ignat@cloudflare.com> wrote:
> On Wed, Mar 8, 2023 at 2:56 AM Hou Tao <houtao@huaweicloud.com> wrote:
> >
> > Hi,
> >
> > On 3/7/2023 10:47 PM, Mike Snitzer wrote:
> > > On Mon, Mar 06 2023 at 9:12P -0500,
> > > Hou Tao <houtao@huaweicloud.com> wrote:
> > >
> > >> Hi,
> > >>
> > >> On 3/7/2023 3:31 AM, Mike Snitzer wrote:
> > >>> On Mon, Mar 06 2023 at 8:49P -0500,
> > >>> Hou Tao <houtao@huaweicloud.com> wrote:
> > >>>
> > >>>> From: Hou Tao <houtao1@huawei.com>
> > >>>>
> > >>>> When neither no_read_workqueue nor no_write_workqueue are enabled,
> > >>>> tasklet_trylock() in crypt_dec_pending() may still return false due to
> > >>>> an uninitialized state, and dm-crypt will do io completion in io_queue
> > >>>> instead of current context unnecessarily.
> > >>> Have you actually experienced this?
> > >> Yes. I had written a bpftrace script to check the completion context of
> > >> blkdev_bio_end_io_simple() when doing direct io read on dm-crypt device. The
> > >> expected context should be unbound workers of crypt_queue, but sometimes the
> > >> context is the bound worker of io_queue.
> > > OK, thanks for clarifying. Curious to know the circumstance (I
> > > thought per-bio-data is zero'd -- but it may be I'm mistaken).
> > The circumstance is just a normal qemu VM running the vanilla kernel for test
> > purpose. According to the implementation of bio_alloc_bioset(), the front pad of
> > bio is not initialized and only bio itself is initialized. AFAIK if
> > CONFIG_INIT_ON_ALLOC_DEFAULT_ON is enabled, per-bio-data may be zeroed.
OK.
> > > From: Mike Snitzer <snitzer@kernel.org>
> > > Date: Mon, 6 Mar 2023 15:58:33 -0500
> > > Subject: [PATCH] dm crypt: conditionally enable code needed for tasklet usecases
> > >
> > > Use jump_label to limit the need for branching, and tasklet_init(),
> > > unless either of the optional "no_read_workqueue" and/or
> > > "no_write_workqueue" features are used.
> > >
> > > Signed-off-by: Mike Snitzer <snitzer@kernel.org>
> > > ---
> > > drivers/md/dm-crypt.c | 35 +++++++++++++++++++++++++++--------
> > > 1 file changed, 27 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> > > index 641457e72603..2d0309ca07f5 100644
> > > --- a/drivers/md/dm-crypt.c
> > > +++ b/drivers/md/dm-crypt.c
> > > @@ -40,6 +40,7 @@
> > > #include <keys/user-type.h>
> > > #include <keys/encrypted-type.h>
> > > #include <keys/trusted-type.h>
> > > +#include <linux/jump_label.h>
> > >
> > > #include <linux/device-mapper.h>
> > >
> > > @@ -85,6 +86,8 @@ struct dm_crypt_io {
> > > struct rb_node rb_node;
> > > } CRYPTO_MINALIGN_ATTR;
> > >
> > > +static DEFINE_STATIC_KEY_FALSE(use_tasklet_enabled);
> > > +
> > > struct dm_crypt_request {
> > > struct convert_context *ctx;
> > > struct scatterlist sg_in[4];
> > > @@ -1730,12 +1733,15 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc,
> > > io->sector = sector;
> > > io->error = 0;
> > > io->ctx.r.req = NULL;
> > > - /*
> > > - * tasklet_init() here to ensure crypt_dec_pending()'s
> > > - * tasklet_trylock() doesn't incorrectly return false
> > > - * even when tasklet isn't in use.
> > > - */
> > > - tasklet_init(&io->tasklet, kcryptd_crypt_tasklet, (unsigned long)&io->work);
> > > + if (static_branch_unlikely(&use_tasklet_enabled)) {
> > > + /*
> > > + * tasklet_init() here to ensure crypt_dec_pending()'s
> > > + * tasklet_trylock() doesn't incorrectly return false
> > > + * even when tasklet isn't in use.
> > > + */
> > > + tasklet_init(&io->tasklet, kcryptd_crypt_tasklet,
> > > + (unsigned long)&io->work);
> > > + }
> > > io->integrity_metadata = NULL;
> > > io->integrity_metadata_from_pool = false;
> > > atomic_set(&io->io_pending, 0);
> > > @@ -1775,6 +1781,10 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
> > > kfree(io->integrity_metadata);
> > >
> > > base_bio->bi_status = error;
> > > + if (!static_branch_unlikely(&use_tasklet_enabled)) {
> > > + bio_endio(base_bio);
> > > + return;
> > > + }
> > Because use_tasklet_enabled can be enabled concurrently, so I think it is still
> > possible that crypt_dec_pending will try-lock an unitialized tasklet if
> > use_tasklet_enabled is enabled when invoking crypt_dec_pending().
Good point, while I think it is probably acceptable given the worst
case is punting the bio_endio to a workqueue for a time ...
> Perhaps instead we can just pass an additional flag from
> tasklet_schedule to indicate to the function that we're running in a
> tasklet. I originally have chosen the tasklet_trylock/unlock hack to
> avoid passing an extra flag. But unitialized memory makes sense as
> well as the desire to avoid calling tasklet_init unconditionally. So
> an extra member in dm_crypt_io might be the most straightforward here.
... I think we should certainly evaluate the use of an extra flag.
Ignat: I'll have a look at implementing it but if you have a patch
already developed please do share.
Thanks,
Mike
next prev parent reply other threads:[~2023-03-08 19:19 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-06 13:49 [dm-devel] [PATCH] dm crypt: initialize tasklet in crypt_io_init() Hou Tao
2023-03-06 13:49 ` Hou Tao
2023-03-06 19:31 ` [dm-devel] " Mike Snitzer
2023-03-06 19:31 ` Mike Snitzer
2023-03-07 2:12 ` [dm-devel] " Hou Tao
2023-03-07 2:12 ` Hou Tao
2023-03-07 14:47 ` [dm-devel] " Mike Snitzer
2023-03-07 14:47 ` Mike Snitzer
2023-03-08 2:56 ` [dm-devel] " Hou Tao
2023-03-08 2:56 ` Hou Tao
2023-03-08 13:55 ` [dm-devel] " Ignat Korchagin
2023-03-08 13:55 ` Ignat Korchagin
2023-03-08 19:19 ` Mike Snitzer [this message]
2023-03-08 19:19 ` Mike Snitzer
2023-03-08 20:27 ` [dm-devel] " Mike Snitzer
2023-03-08 20:27 ` Mike Snitzer
2023-03-09 11:27 ` [dm-devel] " Ignat Korchagin
2023-03-09 11:27 ` Ignat Korchagin
2023-03-09 11:21 ` [dm-devel] " Ignat Korchagin
2023-03-09 11:21 ` Ignat Korchagin
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=ZAjfu0R7rv45J3Dr@redhat.com \
--to=snitzer@kernel.org \
--cc=agk@redhat.com \
--cc=dm-devel@redhat.com \
--cc=houtao1@huawei.com \
--cc=houtao@huaweicloud.com \
--cc=ignat@cloudflare.com \
--cc=linux-kernel@vger.kernel.org \
--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.