* Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.
[not found] ` <87poe13rmm.fsf@notabene.neil.brown.name>
@ 2017-11-20 16:43 ` Mike Snitzer
2017-11-21 0:34 ` [dm-devel] " NeilBrown
0 siblings, 1 reply; 22+ messages in thread
From: Mike Snitzer @ 2017-11-20 16:43 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, linux-block, linux-kernel@vger.kernel.org,
device-mapper development
On Sun, Jun 18, 2017 at 5:36 PM, NeilBrown <neilb@suse.com> wrote:
> On Sun, Jun 18 2017, Jens Axboe wrote:
>
>> On Sun, Jun 18 2017, NeilBrown wrote:
>>> This is a resend of my series of patches working
>>> towards removing the bioset work queues.
>>>
>>> This set is based on for-4.13/block.
>>>
>>> It incorporates the revised versions of all the patches that were
>>> resent following feedback on the last set.
>>>
>>> It also includes a minor grammatic improvement to a comment, and
>>> simple changes to compensate for a couple of changes to the block tree
>>> since the last posting.
>>>
>>> I hope to eventually get rid of the new BIOSET_NEED_RESCUER flag,
>>> but that needs work in dm and probably bcache first.
>>
>> Thanks Neil, applied.
>
> Thanks a lot Jens.
I missed this line of work until now. Not quite sure why I wasn't
cc'd or my review/ack required for the DM changes in this patchset.
But I've now queued this patch for once Linus gets back (reverts DM
changes from commit 47e0fb461f):
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-next&id=c9fdc42ba23eabd1ba7aef199fb9bb4b4fe5c545
As is, it is my understanding that DM has no need for a bio_set's
rescue_workqueue. So its removal would appear to only be gated by
bcache?
But I could be mistaken, moving forward please let me know what you
feel needs doing in DM to make it a better citizen.
Thanks,
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.
2017-11-20 16:43 ` [PATCH 00/13] block: assorted cleanup for bio splitting and cloning Mike Snitzer
@ 2017-11-21 0:34 ` NeilBrown
2017-11-21 1:35 ` Mike Snitzer
0 siblings, 1 reply; 22+ messages in thread
From: NeilBrown @ 2017-11-21 0:34 UTC (permalink / raw)
To: Mike Snitzer
Cc: Jens Axboe, linux-block, device-mapper development,
linux-kernel@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 3892 bytes --]
On Mon, Nov 20 2017, Mike Snitzer wrote:
> On Sun, Jun 18, 2017 at 5:36 PM, NeilBrown <neilb@suse.com> wrote:
>> On Sun, Jun 18 2017, Jens Axboe wrote:
>>
>>> On Sun, Jun 18 2017, NeilBrown wrote:
>>>> This is a resend of my series of patches working
>>>> towards removing the bioset work queues.
>>>>
>>>> This set is based on for-4.13/block.
>>>>
>>>> It incorporates the revised versions of all the patches that were
>>>> resent following feedback on the last set.
>>>>
>>>> It also includes a minor grammatic improvement to a comment, and
>>>> simple changes to compensate for a couple of changes to the block tree
>>>> since the last posting.
>>>>
>>>> I hope to eventually get rid of the new BIOSET_NEED_RESCUER flag,
>>>> but that needs work in dm and probably bcache first.
>>>
>>> Thanks Neil, applied.
>>
>> Thanks a lot Jens.
>
> I missed this line of work until now. Not quite sure why I wasn't
> cc'd or my review/ack required for the DM changes in this patchset.
Hi Mike,
I'm sorry you weren't included on those. My thinking at the time was
probably that they were purely cosmetic changes which made no
functional difference to dm. That is no excuse though and I do
apologize.
>
> But I've now queued this patch for once Linus gets back (reverts DM
> changes from commit 47e0fb461f):
> https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-next&id=c9fdc42ba23eabd1ba7aef199fb9bb4b4fe5c545
This patch does two things.
1/ It removes the BIOSET_NEED_RESCUER flag from biosets created by dm.
This a functional changed over the code from before my patches.
Previously, all biosets were given a rescuer thread.
After my patch set, biosets only got a rescuer thread if
BIOSET_NEED_RESCUER was passed, and it was passed for all biosets.
I then removed it from places were I was certain it wasn't needed.
I didn't remove it from dm because I wasn't certain. Your
patch does remove the flags, which I think is incorrect - see below.
2/ It changes flush_current_bio_list() so that bios allocated from a
bioset that does not have a rescue_workqueue are now added to
the ->rescue_list for their bio_set, and ->rescue_work is queued
on the NULL ->rescue_workqueue, resulting in a NULL dereference.
I suspect you don't want this.
The patch description claims that the patch fixes something, but it
isn't clear to me what it is meant to be fixing.
It makes reference to dbba42d8 which is described as removing an unused
bioset process, though what it actually does is remove an used bioset
(and obvious the process disappears with it). My patch doesn't change
that behavior.
>
> As is, it is my understanding that DM has no need for a bio_set's
> rescue_workqueue. So its removal would appear to only be gated by
> bcache?
>
> But I could be mistaken, moving forward please let me know what you
> feel needs doing in DM to make it a better citizen.
I think you are mistaken.
Please see
https://www.redhat.com/archives/dm-devel/2017-August/msg00310.html
and
https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
for which the thread continues:
https://www.redhat.com/archives/dm-devel/2017-September/msg00001.html
These were sent to you, though most of the conversation happened with
Mikulas.
I think that the patches in those threads explain why dm currently needs
rescuer threads, and shows how dm can be changed to no longer need the
rescuer. I would appreciate your thoughts on these patches. I can
resend them if that would help.
That would then just leave bcache.... I find it a bit of a challenge to
reason about the code in bcache, but if we can remove
BIOSET_NEED_RESCUER from dm, that will be an extra incentive for me to learn :-)
Thanks,
NeilBrown
>
> Thanks,
> Mike
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.
2017-11-21 0:34 ` [dm-devel] " NeilBrown
@ 2017-11-21 1:35 ` Mike Snitzer
2017-11-21 12:10 ` Mike Snitzer
0 siblings, 1 reply; 22+ messages in thread
From: Mike Snitzer @ 2017-11-21 1:35 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, linux-block, device-mapper development,
linux-kernel@vger.kernel.org, Zdenek Kabelac
On Mon, Nov 20 2017 at 7:34pm -0500,
NeilBrown <neilb@suse.com> wrote:
> On Mon, Nov 20 2017, Mike Snitzer wrote:
>
> > On Sun, Jun 18, 2017 at 5:36 PM, NeilBrown <neilb@suse.com> wrote:
> >> On Sun, Jun 18 2017, Jens Axboe wrote:
> >>
> >>> On Sun, Jun 18 2017, NeilBrown wrote:
> >>>> This is a resend of my series of patches working
> >>>> towards removing the bioset work queues.
> >>>>
> >>>> This set is based on for-4.13/block.
> >>>>
> >>>> It incorporates the revised versions of all the patches that were
> >>>> resent following feedback on the last set.
> >>>>
> >>>> It also includes a minor grammatic improvement to a comment, and
> >>>> simple changes to compensate for a couple of changes to the block tree
> >>>> since the last posting.
> >>>>
> >>>> I hope to eventually get rid of the new BIOSET_NEED_RESCUER flag,
> >>>> but that needs work in dm and probably bcache first.
> >>>
> >>> Thanks Neil, applied.
> >>
> >> Thanks a lot Jens.
> >
> > I missed this line of work until now. Not quite sure why I wasn't
> > cc'd or my review/ack required for the DM changes in this patchset.
>
> Hi Mike,
> I'm sorry you weren't included on those. My thinking at the time was
> probably that they were purely cosmetic changes which made no
> functional difference to dm. That is no excuse though and I do
> apologize.
>
> >
> > But I've now queued this patch for once Linus gets back (reverts DM
> > changes from commit 47e0fb461f):
> > https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-next&id=c9fdc42ba23eabd1ba7aef199fb9bb4b4fe5c545
>
> This patch does two things.
> 1/ It removes the BIOSET_NEED_RESCUER flag from biosets created by dm.
> This a functional changed over the code from before my patches.
> Previously, all biosets were given a rescuer thread.
> After my patch set, biosets only got a rescuer thread if
> BIOSET_NEED_RESCUER was passed, and it was passed for all biosets.
> I then removed it from places were I was certain it wasn't needed.
> I didn't remove it from dm because I wasn't certain. Your
> patch does remove the flags, which I think is incorrect - see below.
>
> 2/ It changes flush_current_bio_list() so that bios allocated from a
> bioset that does not have a rescue_workqueue are now added to
> the ->rescue_list for their bio_set, and ->rescue_work is queued
> on the NULL ->rescue_workqueue, resulting in a NULL dereference.
> I suspect you don't want this.
>
> The patch description claims that the patch fixes something, but it
> isn't clear to me what it is meant to be fixing.
>
> It makes reference to dbba42d8 which is described as removing an unused
> bioset process, though what it actually does is remove an used bioset
> (and obvious the process disappears with it). My patch doesn't change
> that behavior.
Well I looked at this because Zdenek reported that with more recent
kernels he is seeing the "bioset" per DM device again (whereas it was
thought to be removed with mikulas' commit dbba42d8 -- but that commit
removed "bioset" only in terms of q->bio_split.
Looks like the q->bio_split bioset is created with BIOSET_NEED_RESCUER
but DM calls bioset_free() for q->bio_split. Strikes me as odd that
"bioset" was removed DM devices until it recently reappeared.
Especially if what you say is accurate (that BIOSET_NEED_RESCUER was
implied with the old code.. I believe you!)
I tried to quickly answer how "bioset" is now re-appearing for DM
devices but I obviously need to put more time to it.
(And my goodness does this bioset rescue workqueue need a better name
than "bioset"! Should include the bdevname too)
> > As is, it is my understanding that DM has no need for a bio_set's
> > rescue_workqueue. So its removal would appear to only be gated by
> > bcache?
> >
> > But I could be mistaken, moving forward please let me know what you
> > feel needs doing in DM to make it a better citizen.
>
> I think you are mistaken.
> Please see
> https://www.redhat.com/archives/dm-devel/2017-August/msg00310.html
> and
> https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
> for which the thread continues:
> https://www.redhat.com/archives/dm-devel/2017-September/msg00001.html
>
> These were sent to you, though most of the conversation happened with
> Mikulas.
>
> I think that the patches in those threads explain why dm currently needs
> rescuer threads, and shows how dm can be changed to no longer need the
> rescuer. I would appreciate your thoughts on these patches. I can
> resend them if that would help.
No need to resend. I'll work through the old threads.
> That would then just leave bcache.... I find it a bit of a challenge to
> reason about the code in bcache, but if we can remove
> BIOSET_NEED_RESCUER from dm, that will be an extra incentive for me to learn :-)
I'm all for properly removing BIOSET_NEED_RESCUER from DM.
I'll look closer at all of this in the morning (for now I'm backing the
patch I referenced out from linux-next)
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.
2017-11-21 1:35 ` Mike Snitzer
@ 2017-11-21 12:10 ` Mike Snitzer
2017-11-21 12:43 ` Mike Snitzer
2017-11-21 19:44 ` [dm-devel] [PATCH 00/13] block: assorted cleanup for bio splitting and cloning NeilBrown
0 siblings, 2 replies; 22+ messages in thread
From: Mike Snitzer @ 2017-11-21 12:10 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, linux-block, device-mapper development,
linux-kernel@vger.kernel.org, Zdenek Kabelac
On Mon, Nov 20 2017 at 8:35pm -0500,
Mike Snitzer <snitzer@redhat.com> wrote:
> On Mon, Nov 20 2017 at 7:34pm -0500,
> NeilBrown <neilb@suse.com> wrote:
>
> > On Mon, Nov 20 2017, Mike Snitzer wrote:
> >
> > >
> > > But I've now queued this patch for once Linus gets back (reverts DM
> > > changes from commit 47e0fb461f):
> > > https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-next&id=c9fdc42ba23eabd1ba7aef199fb9bb4b4fe5c545
> >
> > This patch does two things.
> > 1/ It removes the BIOSET_NEED_RESCUER flag from biosets created by dm.
> > This a functional changed over the code from before my patches.
> > Previously, all biosets were given a rescuer thread.
> > After my patch set, biosets only got a rescuer thread if
> > BIOSET_NEED_RESCUER was passed, and it was passed for all biosets.
> > I then removed it from places were I was certain it wasn't needed.
> > I didn't remove it from dm because I wasn't certain. Your
> > patch does remove the flags, which I think is incorrect - see below.
Yeap, definitely was incorrect. I've dropped the patch.
> > 2/ It changes flush_current_bio_list() so that bios allocated from a
> > bioset that does not have a rescue_workqueue are now added to
> > the ->rescue_list for their bio_set, and ->rescue_work is queued
> > on the NULL ->rescue_workqueue, resulting in a NULL dereference.
> > I suspect you don't want this.
Yes, I see that now.
> > The patch description claims that the patch fixes something, but it
> > isn't clear to me what it is meant to be fixing.
> >
> > It makes reference to dbba42d8 which is described as removing an unused
> > bioset process, though what it actually does is remove an used bioset
> > (and obvious the process disappears with it). My patch doesn't change
> > that behavior.
>
> Well I looked at this because Zdenek reported that with more recent
> kernels he is seeing the "bioset" per DM device again (whereas it was
> thought to be removed with mikulas' commit dbba42d8 -- but that commit
> removed "bioset" only in terms of q->bio_split.
I think Zdenek triggered a false-positive that DM had magically sprouted
a new "bioset" rescue_workqueue. Reality is I cannot see how each
bio-based DM device can avoid having one. And the commit d67a5f4b59
("dm: flush queued bios when process blocks to avoid deadlock") I
referenced earlier very much makes DM depend on it even more.
So apologies for being so off-base (by looking to prematurely revert
DM's use of BIOSET_NEED_RESCUER, etc).
> > Please see
> > https://www.redhat.com/archives/dm-devel/2017-August/msg00310.html
I'll very likely pick these up for 4.16 shortly. But hope to work
through complete removal of DM's use of BIOSET_NEED_RESCUER for 4.16 as
well.
> > and
> > https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
This one [1] needs a lot of review and testing. Particularly against this
test case that Mikulas created to reproduce the snapshot deadlock (same
deadlock that motivated commit dbba42d8):
https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
> > for which the thread continues:
> > https://www.redhat.com/archives/dm-devel/2017-September/msg00001.html
Wish I could clone myself (or Kent, the world needs 2 Kents!) and pursue
this: https://www.redhat.com/archives/dm-devel/2014-May/msg00100.html
Short of that, how would you like to proceed?
> > That would then just leave bcache.... I find it a bit of a challenge to
> > reason about the code in bcache, but if we can remove
> > BIOSET_NEED_RESCUER from dm, that will be an extra incentive for me to learn :-)
>
> I'm all for properly removing BIOSET_NEED_RESCUER from DM.
Should we work to make [1] (above) sure it fixes Mikulas' test case?
I'll set in on reviewing and playing with [1] now.
Thanks,
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.
2017-11-21 12:10 ` Mike Snitzer
@ 2017-11-21 12:43 ` Mike Snitzer
2017-11-21 19:47 ` new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.] Mike Snitzer
2017-11-21 19:44 ` [dm-devel] [PATCH 00/13] block: assorted cleanup for bio splitting and cloning NeilBrown
1 sibling, 1 reply; 22+ messages in thread
From: Mike Snitzer @ 2017-11-21 12:43 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, linux-block, device-mapper development,
linux-kernel@vger.kernel.org, Zdenek Kabelac
On Tue, Nov 21 2017 at 7:10am -0500,
Mike Snitzer <snitzer@redhat.com> wrote:
> On Mon, Nov 20 2017 at 8:35pm -0500,
> Mike Snitzer <snitzer@redhat.com> wrote:
>
> > On Mon, Nov 20 2017 at 7:34pm -0500,
> > NeilBrown <neilb@suse.com> wrote:
> >
> > > Please see
> > > https://www.redhat.com/archives/dm-devel/2017-August/msg00310.html
>
> I'll very likely pick these up for 4.16 shortly. But hope to work
> through complete removal of DM's use of BIOSET_NEED_RESCUER for 4.16 as
> well.
>
> > > and
> > > https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
>
> This one [1] needs a lot of review and testing. Particularly against this
> test case that Mikulas created to reproduce the snapshot deadlock (same
> deadlock that motivated commit dbba42d8):
> https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
...
> Short of that, how would you like to proceed?
>
> > > That would then just leave bcache.... I find it a bit of a challenge to
> > > reason about the code in bcache, but if we can remove
> > > BIOSET_NEED_RESCUER from dm, that will be an extra incentive for me to learn :-)
> >
> > I'm all for properly removing BIOSET_NEED_RESCUER from DM.
>
> Should we work to make [1] (above) sure it fixes Mikulas' test case?
>
> I'll set in on reviewing and playing with [1] now.
Decided it a better use of my time to review and then hopefully use the
block-core's bio splitting infrastructure in DM. Been meaning to do
that for quite a while anyway. This mail from you just made it all the
more clear that needs doing:
https://www.redhat.com/archives/dm-devel/2017-September/msg00098.html
So I will start here on this patch you proposed:
https://www.redhat.com/archives/dm-devel/2017-September/msg00091.html
(of note, this patch slipped through the cracks because I was recovering
from injury when it originally came through).
Once DM is using q->bio_split I'll come back to this patch (aka
"[1]") as a starting point for the follow-on work to remove DM's use of
BIOSET_NEED_RESCUER:
https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.
2017-11-21 12:10 ` Mike Snitzer
2017-11-21 12:43 ` Mike Snitzer
@ 2017-11-21 19:44 ` NeilBrown
2017-11-21 19:50 ` Mike Snitzer
1 sibling, 1 reply; 22+ messages in thread
From: NeilBrown @ 2017-11-21 19:44 UTC (permalink / raw)
To: Mike Snitzer
Cc: Jens Axboe, linux-block, device-mapper development,
linux-kernel@vger.kernel.org, Zdenek Kabelac
[-- Attachment #1: Type: text/plain, Size: 4906 bytes --]
On Tue, Nov 21 2017, Mike Snitzer wrote:
> On Mon, Nov 20 2017 at 8:35pm -0500,
> Mike Snitzer <snitzer@redhat.com> wrote:
>
>> On Mon, Nov 20 2017 at 7:34pm -0500,
>> NeilBrown <neilb@suse.com> wrote:
>>
>> > On Mon, Nov 20 2017, Mike Snitzer wrote:
>> >
>> > >
>> > > But I've now queued this patch for once Linus gets back (reverts DM
>> > > changes from commit 47e0fb461f):
>> > > https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-next&id=c9fdc42ba23eabd1ba7aef199fb9bb4b4fe5c545
>> >
>> > This patch does two things.
>> > 1/ It removes the BIOSET_NEED_RESCUER flag from biosets created by dm.
>> > This a functional changed over the code from before my patches.
>> > Previously, all biosets were given a rescuer thread.
>> > After my patch set, biosets only got a rescuer thread if
>> > BIOSET_NEED_RESCUER was passed, and it was passed for all biosets.
>> > I then removed it from places were I was certain it wasn't needed.
>> > I didn't remove it from dm because I wasn't certain. Your
>> > patch does remove the flags, which I think is incorrect - see below.
>
> Yeap, definitely was incorrect. I've dropped the patch.
>
>> > 2/ It changes flush_current_bio_list() so that bios allocated from a
>> > bioset that does not have a rescue_workqueue are now added to
>> > the ->rescue_list for their bio_set, and ->rescue_work is queued
>> > on the NULL ->rescue_workqueue, resulting in a NULL dereference.
>> > I suspect you don't want this.
>
> Yes, I see that now.
>
>> > The patch description claims that the patch fixes something, but it
>> > isn't clear to me what it is meant to be fixing.
>> >
>> > It makes reference to dbba42d8 which is described as removing an unused
>> > bioset process, though what it actually does is remove an used bioset
>> > (and obvious the process disappears with it). My patch doesn't change
>> > that behavior.
>>
>> Well I looked at this because Zdenek reported that with more recent
>> kernels he is seeing the "bioset" per DM device again (whereas it was
>> thought to be removed with mikulas' commit dbba42d8 -- but that commit
>> removed "bioset" only in terms of q->bio_split.
>
> I think Zdenek triggered a false-positive that DM had magically sprouted
> a new "bioset" rescue_workqueue. Reality is I cannot see how each
> bio-based DM device can avoid having one. And the commit d67a5f4b59
> ("dm: flush queued bios when process blocks to avoid deadlock") I
> referenced earlier very much makes DM depend on it even more.
>
> So apologies for being so off-base (by looking to prematurely revert
> DM's use of BIOSET_NEED_RESCUER, etc).
>
>> > Please see
>> > https://www.redhat.com/archives/dm-devel/2017-August/msg00310.html
>
> I'll very likely pick these up for 4.16 shortly. But hope to work
> through complete removal of DM's use of BIOSET_NEED_RESCUER for 4.16 as
> well.
>
>> > and
>> > https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
>
> This one [1] needs a lot of review and testing. Particularly against this
> test case that Mikulas created to reproduce the snapshot deadlock (same
> deadlock that motivated commit dbba42d8):
> https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
Thanks for that link. I'll try to make time to experiment with the test
code and confirm my proposed approach doesn't break it.
>
>> > for which the thread continues:
>> > https://www.redhat.com/archives/dm-devel/2017-September/msg00001.html
>
> Wish I could clone myself (or Kent, the world needs 2 Kents!) and pursue
> this: https://www.redhat.com/archives/dm-devel/2014-May/msg00100.html
In that email Kent mentions "punt off to a per request_queue workqueue".
That "per request_queue workqueue" is what I'm trying to get rid of. I
don't think this is a good direction.
>
> Short of that, how would you like to proceed?
I'd like to confirm that my approach
1/ doesn't re-introduce a deadlock
2/ doesn't hurt performance
and then merge it.
Though to be honest, I don't recall exactly what "my approach" is.
Your next email picks out two important patches which probably cover
it. If/when I get to do the testing I'll let you know how it goes.
Thanks,
NeilBrown
>
>> > That would then just leave bcache.... I find it a bit of a challenge to
>> > reason about the code in bcache, but if we can remove
>> > BIOSET_NEED_RESCUER from dm, that will be an extra incentive for me to learn :-)
>>
>> I'm all for properly removing BIOSET_NEED_RESCUER from DM.
>
> Should we work to make [1] (above) sure it fixes Mikulas' test case?
>
> I'll set in on reviewing and playing with [1] now.
>
> Thanks,
> Mike
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.]
2017-11-21 12:43 ` Mike Snitzer
@ 2017-11-21 19:47 ` Mike Snitzer
2017-11-21 21:23 ` [dm-devel] " Mikulas Patocka
0 siblings, 1 reply; 22+ messages in thread
From: Mike Snitzer @ 2017-11-21 19:47 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, linux-block, device-mapper development,
linux-kernel@vger.kernel.org, Zdenek Kabelac, Mikulas Patocka
On Tue, Nov 21 2017 at 7:43am -0500,
Mike Snitzer <snitzer@redhat.com> wrote:
> Decided it a better use of my time to review and then hopefully use the
> block-core's bio splitting infrastructure in DM. Been meaning to do
> that for quite a while anyway. This mail from you just made it all the
> more clear that needs doing:
> https://www.redhat.com/archives/dm-devel/2017-September/msg00098.html
>
> So I will start here on this patch you proposed:
> https://www.redhat.com/archives/dm-devel/2017-September/msg00091.html
> (of note, this patch slipped through the cracks because I was recovering
> from injury when it originally came through).
>
> Once DM is using q->bio_split I'll come back to this patch (aka
> "[1]") as a starting point for the follow-on work to remove DM's use of
> BIOSET_NEED_RESCUER:
> https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
Hey Neil,
Good news! All your code works ;)
(well after 1 fixup due to a cut-n-paste bug.. the code you added to
dm_wq_work() to process the md->rescued bio_list was operating on
the md->deferred bio_list due to cut-n-paste from code you copied from
just below it)
I split your code out some to make it more reviewable. I also tweaked
headers accordingly.
Please see this branch (which _will_ get rebased between now and the
4.16 merge window):
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/log/?h=dm-4.16
I successfully tested these changes using Mikulas' test program that
reproduces the snapshot deadlock:
https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
I'll throw various other DM testsuites at it to verify they all look
good (e.g. thinp, cache, multipath).
I'm open to all suggestions about changes you'd like to see (either to
these patches or anything you'd like to layer ontop of them).
Thanks for all your work, much appreciated!
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.
2017-11-21 19:44 ` [dm-devel] [PATCH 00/13] block: assorted cleanup for bio splitting and cloning NeilBrown
@ 2017-11-21 19:50 ` Mike Snitzer
0 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2017-11-21 19:50 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, linux-block, device-mapper development,
linux-kernel@vger.kernel.org, Zdenek Kabelac
On Tue, Nov 21 2017 at 2:44pm -0500,
NeilBrown <neilb@suse.com> wrote:
> On Tue, Nov 21 2017, Mike Snitzer wrote:
>
> > On Mon, Nov 20 2017 at 8:35pm -0500,
> > Mike Snitzer <snitzer@redhat.com> wrote:
> >
> >> On Mon, Nov 20 2017 at 7:34pm -0500,
> >> NeilBrown <neilb@suse.com> wrote:
> >>
> >> > On Mon, Nov 20 2017, Mike Snitzer wrote:
> >> >
> >> > >
> >> > > But I've now queued this patch for once Linus gets back (reverts DM
> >> > > changes from commit 47e0fb461f):
> >> > > https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-next&id=c9fdc42ba23eabd1ba7aef199fb9bb4b4fe5c545
> >> >
> >> > This patch does two things.
> >> > 1/ It removes the BIOSET_NEED_RESCUER flag from biosets created by dm.
> >> > This a functional changed over the code from before my patches.
> >> > Previously, all biosets were given a rescuer thread.
> >> > After my patch set, biosets only got a rescuer thread if
> >> > BIOSET_NEED_RESCUER was passed, and it was passed for all biosets.
> >> > I then removed it from places were I was certain it wasn't needed.
> >> > I didn't remove it from dm because I wasn't certain. Your
> >> > patch does remove the flags, which I think is incorrect - see below.
> >
> > Yeap, definitely was incorrect. I've dropped the patch.
> >
> >> > 2/ It changes flush_current_bio_list() so that bios allocated from a
> >> > bioset that does not have a rescue_workqueue are now added to
> >> > the ->rescue_list for their bio_set, and ->rescue_work is queued
> >> > on the NULL ->rescue_workqueue, resulting in a NULL dereference.
> >> > I suspect you don't want this.
> >
> > Yes, I see that now.
> >
> >> > The patch description claims that the patch fixes something, but it
> >> > isn't clear to me what it is meant to be fixing.
> >> >
> >> > It makes reference to dbba42d8 which is described as removing an unused
> >> > bioset process, though what it actually does is remove an used bioset
> >> > (and obvious the process disappears with it). My patch doesn't change
> >> > that behavior.
> >>
> >> Well I looked at this because Zdenek reported that with more recent
> >> kernels he is seeing the "bioset" per DM device again (whereas it was
> >> thought to be removed with mikulas' commit dbba42d8 -- but that commit
> >> removed "bioset" only in terms of q->bio_split.
> >
> > I think Zdenek triggered a false-positive that DM had magically sprouted
> > a new "bioset" rescue_workqueue. Reality is I cannot see how each
> > bio-based DM device can avoid having one. And the commit d67a5f4b59
> > ("dm: flush queued bios when process blocks to avoid deadlock") I
> > referenced earlier very much makes DM depend on it even more.
> >
> > So apologies for being so off-base (by looking to prematurely revert
> > DM's use of BIOSET_NEED_RESCUER, etc).
> >
> >> > Please see
> >> > https://www.redhat.com/archives/dm-devel/2017-August/msg00310.html
> >
> > I'll very likely pick these up for 4.16 shortly. But hope to work
> > through complete removal of DM's use of BIOSET_NEED_RESCUER for 4.16 as
> > well.
> >
> >> > and
> >> > https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
> >
> > This one [1] needs a lot of review and testing. Particularly against this
> > test case that Mikulas created to reproduce the snapshot deadlock (same
> > deadlock that motivated commit dbba42d8):
> > https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
>
> Thanks for that link. I'll try to make time to experiment with the test
> code and confirm my proposed approach doesn't break it.
>
> >
> >> > for which the thread continues:
> >> > https://www.redhat.com/archives/dm-devel/2017-September/msg00001.html
> >
> > Wish I could clone myself (or Kent, the world needs 2 Kents!) and pursue
> > this: https://www.redhat.com/archives/dm-devel/2014-May/msg00100.html
>
> In that email Kent mentions "punt off to a per request_queue workqueue".
>
> That "per request_queue workqueue" is what I'm trying to get rid of. I
> don't think this is a good direction.
>
> >
> > Short of that, how would you like to proceed?
>
> I'd like to confirm that my approach
> 1/ doesn't re-introduce a deadlock
> 2/ doesn't hurt performance
> and then merge it.
>
> Though to be honest, I don't recall exactly what "my approach" is.
> Your next email picks out two important patches which probably cover
> it. If/when I get to do the testing I'll let you know how it goes.
I _think_ I've done the heavy lifting of what you likely had in mind
( please see: https://lkml.org/lkml/2017/11/21/567 )
Now what is left is another once-over from you to verify you're happy
with the code and patch headers, etc.
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.]
2017-11-21 19:47 ` new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.] Mike Snitzer
@ 2017-11-21 21:23 ` Mikulas Patocka
2017-11-21 22:51 ` new patchset to eliminate DM's use of BIOSET_NEED_RESCUER Mike Snitzer
2017-11-21 23:03 ` [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.] NeilBrown
0 siblings, 2 replies; 22+ messages in thread
From: Mikulas Patocka @ 2017-11-21 21:23 UTC (permalink / raw)
To: Mike Snitzer
Cc: NeilBrown, Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Zdenek Kabelac
On Tue, 21 Nov 2017, Mike Snitzer wrote:
> On Tue, Nov 21 2017 at 7:43am -0500,
> Mike Snitzer <snitzer@redhat.com> wrote:
>
> > Decided it a better use of my time to review and then hopefully use the
> > block-core's bio splitting infrastructure in DM. Been meaning to do
> > that for quite a while anyway. This mail from you just made it all the
> > more clear that needs doing:
> > https://www.redhat.com/archives/dm-devel/2017-September/msg00098.html
> >
> > So I will start here on this patch you proposed:
> > https://www.redhat.com/archives/dm-devel/2017-September/msg00091.html
> > (of note, this patch slipped through the cracks because I was recovering
> > from injury when it originally came through).
> >
> > Once DM is using q->bio_split I'll come back to this patch (aka
> > "[1]") as a starting point for the follow-on work to remove DM's use of
> > BIOSET_NEED_RESCUER:
> > https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
>
> Hey Neil,
>
> Good news! All your code works ;)
>
> (well after 1 fixup due to a cut-n-paste bug.. the code you added to
> dm_wq_work() to process the md->rescued bio_list was operating on
> the md->deferred bio_list due to cut-n-paste from code you copied from
> just below it)
>
> I split your code out some to make it more reviewable. I also tweaked
> headers accordingly.
>
> Please see this branch (which _will_ get rebased between now and the
> 4.16 merge window):
> https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/log/?h=dm-4.16
>
> I successfully tested these changes using Mikulas' test program that
> reproduces the snapshot deadlock:
> https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
>
> I'll throw various other DM testsuites at it to verify they all look
> good (e.g. thinp, cache, multipath).
>
> I'm open to all suggestions about changes you'd like to see (either to
> these patches or anything you'd like to layer ontop of them).
>
> Thanks for all your work, much appreciated!
> Mike
This is not correct:
2206 static void dm_wq_work(struct work_struct *work)
2207 {
2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
2209 struct bio *bio;
2210 int srcu_idx;
2211 struct dm_table *map;
2212
2213 if (!bio_list_empty(&md->rescued)) {
2214 struct bio_list list;
2215 spin_lock_irq(&md->deferred_lock);
2216 list = md->rescued;
2217 bio_list_init(&md->rescued);
2218 spin_unlock_irq(&md->deferred_lock);
2219 while ((bio = bio_list_pop(&list)))
2220 generic_make_request(bio);
2221 }
2222
2223 map = dm_get_live_table(md, &srcu_idx);
2224
2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
2226 spin_lock_irq(&md->deferred_lock);
2227 bio = bio_list_pop(&md->deferred);
2228 spin_unlock_irq(&md->deferred_lock);
2229
2230 if (!bio)
2231 break;
2232
2233 if (dm_request_based(md))
2234 generic_make_request(bio);
2235 else
2236 __split_and_process_bio(md, map, bio);
2237 }
2238
2239 dm_put_live_table(md, srcu_idx);
2240 }
You can see that if we are in dm_wq_work in __split_and_process_bio, we
will not process md->rescued list.
The processing of md->rescued is also wrong - bios for different devices
must be offloaded to different helper threads, so that processing a bio
for a lower device doesn't depend on processing a bio for a higher device.
If you offload all the bios on current->bio_list to the same thread, the
bios still depend on each other and the deadlock will still happen.
Mikulas
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-21 21:23 ` [dm-devel] " Mikulas Patocka
@ 2017-11-21 22:51 ` Mike Snitzer
2017-11-22 1:21 ` Mikulas Patocka
2017-11-21 23:03 ` [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.] NeilBrown
1 sibling, 1 reply; 22+ messages in thread
From: Mike Snitzer @ 2017-11-21 22:51 UTC (permalink / raw)
To: Mikulas Patocka
Cc: NeilBrown, Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Zdenek Kabelac
On Tue, Nov 21 2017 at 4:23pm -0500,
Mikulas Patocka <mpatocka@redhat.com> wrote:
>
>
> On Tue, 21 Nov 2017, Mike Snitzer wrote:
>
> > On Tue, Nov 21 2017 at 7:43am -0500,
> > Mike Snitzer <snitzer@redhat.com> wrote:
> >
> > > Decided it a better use of my time to review and then hopefully use the
> > > block-core's bio splitting infrastructure in DM. Been meaning to do
> > > that for quite a while anyway. This mail from you just made it all the
> > > more clear that needs doing:
> > > https://www.redhat.com/archives/dm-devel/2017-September/msg00098.html
> > >
> > > So I will start here on this patch you proposed:
> > > https://www.redhat.com/archives/dm-devel/2017-September/msg00091.html
> > > (of note, this patch slipped through the cracks because I was recovering
> > > from injury when it originally came through).
> > >
> > > Once DM is using q->bio_split I'll come back to this patch (aka
> > > "[1]") as a starting point for the follow-on work to remove DM's use of
> > > BIOSET_NEED_RESCUER:
> > > https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
> >
> > Hey Neil,
> >
> > Good news! All your code works ;)
> >
> > (well after 1 fixup due to a cut-n-paste bug.. the code you added to
> > dm_wq_work() to process the md->rescued bio_list was operating on
> > the md->deferred bio_list due to cut-n-paste from code you copied from
> > just below it)
> >
> > I split your code out some to make it more reviewable. I also tweaked
> > headers accordingly.
> >
> > Please see this branch (which _will_ get rebased between now and the
> > 4.16 merge window):
> > https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/log/?h=dm-4.16
> >
> > I successfully tested these changes using Mikulas' test program that
> > reproduces the snapshot deadlock:
> > https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
> >
> > I'll throw various other DM testsuites at it to verify they all look
> > good (e.g. thinp, cache, multipath).
> >
> > I'm open to all suggestions about changes you'd like to see (either to
> > these patches or anything you'd like to layer ontop of them).
> >
> > Thanks for all your work, much appreciated!
> > Mike
>
> This is not correct:
>
> 2206 static void dm_wq_work(struct work_struct *work)
> 2207 {
> 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
> 2209 struct bio *bio;
> 2210 int srcu_idx;
> 2211 struct dm_table *map;
> 2212
> 2213 if (!bio_list_empty(&md->rescued)) {
> 2214 struct bio_list list;
> 2215 spin_lock_irq(&md->deferred_lock);
> 2216 list = md->rescued;
> 2217 bio_list_init(&md->rescued);
> 2218 spin_unlock_irq(&md->deferred_lock);
> 2219 while ((bio = bio_list_pop(&list)))
> 2220 generic_make_request(bio);
> 2221 }
> 2222
> 2223 map = dm_get_live_table(md, &srcu_idx);
> 2224
> 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
> 2226 spin_lock_irq(&md->deferred_lock);
> 2227 bio = bio_list_pop(&md->deferred);
> 2228 spin_unlock_irq(&md->deferred_lock);
> 2229
> 2230 if (!bio)
> 2231 break;
> 2232
> 2233 if (dm_request_based(md))
> 2234 generic_make_request(bio);
> 2235 else
> 2236 __split_and_process_bio(md, map, bio);
> 2237 }
> 2238
> 2239 dm_put_live_table(md, srcu_idx);
> 2240 }
>
> You can see that if we are in dm_wq_work in __split_and_process_bio, we
> will not process md->rescued list.
Can you elaborate further? We cannot be "in dm_wq_work in
__split_and_process_bio" simultaneously. Do you mean as a side-effect
of scheduling away from __split_and_process_bio?
The more detail you can share the better.
> The processing of md->rescued is also wrong - bios for different devices
> must be offloaded to different helper threads, so that processing a bio
> for a lower device doesn't depend on processing a bio for a higher device.
> If you offload all the bios on current->bio_list to the same thread, the
> bios still depend on each other and the deadlock will still happen.
Commit 325738403 ("dm: revise 'rescue' strategy for bio-based bioset
allocations") speaks to this with:
"Note that only current->bio_list[0] is offloaded. current->bio_list[1]
contains bios that were scheduled *before* the current one started, so
they must have been submitted from higher up the stack, and we cannot be
waiting for them here (thanks to the "dm: ensure bio submission follows
a depth-first tree walk" commit). Also, we now rescue *all* bios on the
list as there is nothing to be gained by being more selective."
And again: this patchset passes your dm-snapshot deadlock test. Is
that test somehow lacking?
Or do you see a hypothetical case where a deadlock is still possible?
That is of less concern. I'd prefer that we tackle problems for
targets, and associated scenarios, that we currently support.
Either way, happy to review this with you further. Any fixes are
welcomed too. But I'd like us to head in a direction that this patchset
is taking us. Specifically: away from DM relying on BIOSET_NEED_RESCUER.
Thanks,
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.]
2017-11-21 21:23 ` [dm-devel] " Mikulas Patocka
2017-11-21 22:51 ` new patchset to eliminate DM's use of BIOSET_NEED_RESCUER Mike Snitzer
@ 2017-11-21 23:03 ` NeilBrown
1 sibling, 0 replies; 22+ messages in thread
From: NeilBrown @ 2017-11-21 23:03 UTC (permalink / raw)
To: Mikulas Patocka, Mike Snitzer
Cc: Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Zdenek Kabelac
[-- Attachment #1: Type: text/plain, Size: 5643 bytes --]
On Tue, Nov 21 2017, Mikulas Patocka wrote:
> On Tue, 21 Nov 2017, Mike Snitzer wrote:
>
>> On Tue, Nov 21 2017 at 7:43am -0500,
>> Mike Snitzer <snitzer@redhat.com> wrote:
>>
>> > Decided it a better use of my time to review and then hopefully use the
>> > block-core's bio splitting infrastructure in DM. Been meaning to do
>> > that for quite a while anyway. This mail from you just made it all the
>> > more clear that needs doing:
>> > https://www.redhat.com/archives/dm-devel/2017-September/msg00098.html
>> >
>> > So I will start here on this patch you proposed:
>> > https://www.redhat.com/archives/dm-devel/2017-September/msg00091.html
>> > (of note, this patch slipped through the cracks because I was recovering
>> > from injury when it originally came through).
>> >
>> > Once DM is using q->bio_split I'll come back to this patch (aka
>> > "[1]") as a starting point for the follow-on work to remove DM's use of
>> > BIOSET_NEED_RESCUER:
>> > https://www.redhat.com/archives/dm-devel/2017-August/msg00315.html
>>
>> Hey Neil,
>>
>> Good news! All your code works ;)
>>
>> (well after 1 fixup due to a cut-n-paste bug.. the code you added to
>> dm_wq_work() to process the md->rescued bio_list was operating on
>> the md->deferred bio_list due to cut-n-paste from code you copied from
>> just below it)
>>
>> I split your code out some to make it more reviewable. I also tweaked
>> headers accordingly.
>>
>> Please see this branch (which _will_ get rebased between now and the
>> 4.16 merge window):
>> https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/log/?h=dm-4.16
>>
>> I successfully tested these changes using Mikulas' test program that
>> reproduces the snapshot deadlock:
>> https://www.redhat.com/archives/dm-devel/2017-January/msg00064.html
>>
>> I'll throw various other DM testsuites at it to verify they all look
>> good (e.g. thinp, cache, multipath).
>>
>> I'm open to all suggestions about changes you'd like to see (either to
>> these patches or anything you'd like to layer ontop of them).
>>
>> Thanks for all your work, much appreciated!
>> Mike
>
> This is not correct:
Thanks for your review!
>
> 2206 static void dm_wq_work(struct work_struct *work)
> 2207 {
> 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
> 2209 struct bio *bio;
> 2210 int srcu_idx;
> 2211 struct dm_table *map;
> 2212
> 2213 if (!bio_list_empty(&md->rescued)) {
> 2214 struct bio_list list;
> 2215 spin_lock_irq(&md->deferred_lock);
> 2216 list = md->rescued;
> 2217 bio_list_init(&md->rescued);
> 2218 spin_unlock_irq(&md->deferred_lock);
> 2219 while ((bio = bio_list_pop(&list)))
> 2220 generic_make_request(bio);
> 2221 }
> 2222
> 2223 map = dm_get_live_table(md, &srcu_idx);
> 2224
> 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
> 2226 spin_lock_irq(&md->deferred_lock);
> 2227 bio = bio_list_pop(&md->deferred);
> 2228 spin_unlock_irq(&md->deferred_lock);
> 2229
> 2230 if (!bio)
> 2231 break;
> 2232
> 2233 if (dm_request_based(md))
> 2234 generic_make_request(bio);
> 2235 else
> 2236 __split_and_process_bio(md, map, bio);
> 2237 }
> 2238
> 2239 dm_put_live_table(md, srcu_idx);
> 2240 }
>
> You can see that if we are in dm_wq_work in __split_and_process_bio, we
> will not process md->rescued list.
Correct, but md->rescued will be empty, or irrelevant.
The first section of dm_wq_work ensures ->rescued is empty.
When __split_and_process_bio() calls generic_make_request() (indirectly
through one or more targets) they will not be recursive calls,
so nothing will be added to current->bio_list[0] and nothing
will be moved to md->rescued. Each generic_make_request() will
completely submit the request in the lower level devel.
Some other thread could call generic_make_request on this dm device and
result in bios appeared on md->rescued. These bios could only be a
problem if something that __split_and_process_bio calls might wait for
them. I don't think that happens (at least I don't think it should...).
>
> The processing of md->rescued is also wrong - bios for different devices
> must be offloaded to different helper threads, so that processing a bio
> for a lower device doesn't depend on processing a bio for a higher device.
> If you offload all the bios on current->bio_list to the same thread, the
> bios still depend on each other and the deadlock will still happen.
bios on current->bio_list[0] are not allowed to depend on each other
except that later bios can depend on earlier bios. They are all for a
lower-level device and should be largely independent.
The sorting that generic_make_request now does ensure that a bio for a
higher level device is never processed when a bio for a lower level
device, that it might depend on, is stuck on current->bio_list.
So I don't think there is a problem here.
Do you find this argument at all convincing?
Thanks,
NeilBrown
>
> Mikulas
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-21 22:51 ` new patchset to eliminate DM's use of BIOSET_NEED_RESCUER Mike Snitzer
@ 2017-11-22 1:21 ` Mikulas Patocka
2017-11-22 2:32 ` Mike Snitzer
2017-11-22 4:00 ` [dm-devel] " NeilBrown
0 siblings, 2 replies; 22+ messages in thread
From: Mikulas Patocka @ 2017-11-22 1:21 UTC (permalink / raw)
To: Mike Snitzer
Cc: NeilBrown, Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Zdenek Kabelac
On Tue, 21 Nov 2017, Mike Snitzer wrote:
> On Tue, Nov 21 2017 at 4:23pm -0500,
> Mikulas Patocka <mpatocka@redhat.com> wrote:
>
> > This is not correct:
> >
> > 2206 static void dm_wq_work(struct work_struct *work)
> > 2207 {
> > 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
> > 2209 struct bio *bio;
> > 2210 int srcu_idx;
> > 2211 struct dm_table *map;
> > 2212
> > 2213 if (!bio_list_empty(&md->rescued)) {
> > 2214 struct bio_list list;
> > 2215 spin_lock_irq(&md->deferred_lock);
> > 2216 list = md->rescued;
> > 2217 bio_list_init(&md->rescued);
> > 2218 spin_unlock_irq(&md->deferred_lock);
> > 2219 while ((bio = bio_list_pop(&list)))
> > 2220 generic_make_request(bio);
> > 2221 }
> > 2222
> > 2223 map = dm_get_live_table(md, &srcu_idx);
> > 2224
> > 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
> > 2226 spin_lock_irq(&md->deferred_lock);
> > 2227 bio = bio_list_pop(&md->deferred);
> > 2228 spin_unlock_irq(&md->deferred_lock);
> > 2229
> > 2230 if (!bio)
> > 2231 break;
> > 2232
> > 2233 if (dm_request_based(md))
> > 2234 generic_make_request(bio);
> > 2235 else
> > 2236 __split_and_process_bio(md, map, bio);
> > 2237 }
> > 2238
> > 2239 dm_put_live_table(md, srcu_idx);
> > 2240 }
> >
> > You can see that if we are in dm_wq_work in __split_and_process_bio, we
> > will not process md->rescued list.
>
> Can you elaborate further? We cannot be "in dm_wq_work in
> __split_and_process_bio" simultaneously. Do you mean as a side-effect
> of scheduling away from __split_and_process_bio?
>
> The more detail you can share the better.
Suppose this scenario:
* dm_wq_work calls __split_and_process_bio
* __split_and_process_bio eventually reaches the function snapshot_map
* snapshot_map attempts to take the snapshot lock
* the snapshot lock could be released only if some bios submitted by the
snapshot driver to the underlying device complete
* the bios submitted to the underlying device were already offloaded by
some other task and they are waiting on the list md->rescued
* the bios waiting on md->rescued are not processed, because dm_wq_work is
blocked in snapshot_map (called from __split_and_process_bio)
> > The processing of md->rescued is also wrong - bios for different devices
> > must be offloaded to different helper threads, so that processing a bio
> > for a lower device doesn't depend on processing a bio for a higher device.
> > If you offload all the bios on current->bio_list to the same thread, the
> > bios still depend on each other and the deadlock will still happen.
>
> Commit 325738403 ("dm: revise 'rescue' strategy for bio-based bioset
> allocations") speaks to this with:
>
> "Note that only current->bio_list[0] is offloaded. current->bio_list[1]
> contains bios that were scheduled *before* the current one started, so
> they must have been submitted from higher up the stack, and we cannot be
> waiting for them here (thanks to the "dm: ensure bio submission follows
> a depth-first tree walk" commit). Also, we now rescue *all* bios on the
> list as there is nothing to be gained by being more selective."
I think you are right - if we only offload current->bio_list[0], then
mixing of dependent bios on the offloaded list won't happen.
> And again: this patchset passes your dm-snapshot deadlock test. Is
> that test somehow lacking?
With your patchset, the deadlock would happen only if bios are queued on
&md->deferred - and that happens only in case of resume or if we are
processing REQ_PREFLUSH with non-zero data size.
So, the simple test that I wrote doesn't trigger it, but a more complex
test involving REQ_PREFLUSH could.
> Or do you see a hypothetical case where a deadlock is still possible?
> That is of less concern. I'd prefer that we tackle problems for
> targets, and associated scenarios, that we currently support.
>
> Either way, happy to review this with you further. Any fixes are
> welcomed too. But I'd like us to head in a direction that this patchset
> is taking us. Specifically: away from DM relying on BIOSET_NEED_RESCUER.
>
> Thanks,
> Mike
Mikulas
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-22 1:21 ` Mikulas Patocka
@ 2017-11-22 2:32 ` Mike Snitzer
2017-11-22 4:00 ` [dm-devel] " NeilBrown
1 sibling, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2017-11-22 2:32 UTC (permalink / raw)
To: Mikulas Patocka
Cc: NeilBrown, Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Zdenek Kabelac
On Tue, Nov 21 2017 at 8:21pm -0500,
Mikulas Patocka <mpatocka@redhat.com> wrote:
>
>
> On Tue, 21 Nov 2017, Mike Snitzer wrote:
>
> > On Tue, Nov 21 2017 at 4:23pm -0500,
> > Mikulas Patocka <mpatocka@redhat.com> wrote:
> >
> > > This is not correct:
> > >
> > > 2206 static void dm_wq_work(struct work_struct *work)
> > > 2207 {
> > > 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
> > > 2209 struct bio *bio;
> > > 2210 int srcu_idx;
> > > 2211 struct dm_table *map;
> > > 2212
> > > 2213 if (!bio_list_empty(&md->rescued)) {
> > > 2214 struct bio_list list;
> > > 2215 spin_lock_irq(&md->deferred_lock);
> > > 2216 list = md->rescued;
> > > 2217 bio_list_init(&md->rescued);
> > > 2218 spin_unlock_irq(&md->deferred_lock);
> > > 2219 while ((bio = bio_list_pop(&list)))
> > > 2220 generic_make_request(bio);
> > > 2221 }
> > > 2222
> > > 2223 map = dm_get_live_table(md, &srcu_idx);
> > > 2224
> > > 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
> > > 2226 spin_lock_irq(&md->deferred_lock);
> > > 2227 bio = bio_list_pop(&md->deferred);
> > > 2228 spin_unlock_irq(&md->deferred_lock);
> > > 2229
> > > 2230 if (!bio)
> > > 2231 break;
> > > 2232
> > > 2233 if (dm_request_based(md))
> > > 2234 generic_make_request(bio);
> > > 2235 else
> > > 2236 __split_and_process_bio(md, map, bio);
> > > 2237 }
> > > 2238
> > > 2239 dm_put_live_table(md, srcu_idx);
> > > 2240 }
> > >
> > > You can see that if we are in dm_wq_work in __split_and_process_bio, we
> > > will not process md->rescued list.
> >
> > Can you elaborate further? We cannot be "in dm_wq_work in
> > __split_and_process_bio" simultaneously. Do you mean as a side-effect
> > of scheduling away from __split_and_process_bio?
> >
> > The more detail you can share the better.
>
> Suppose this scenario:
>
> * dm_wq_work calls __split_and_process_bio
Right, I later realized this was the call chain you were referring to.
Not sure how I missed it the first time around.
> * __split_and_process_bio eventually reaches the function snapshot_map
> * snapshot_map attempts to take the snapshot lock
>
> * the snapshot lock could be released only if some bios submitted by the
> snapshot driver to the underlying device complete
> * the bios submitted to the underlying device were already offloaded by
> some other task and they are waiting on the list md->rescued
> * the bios waiting on md->rescued are not processed, because dm_wq_work is
> blocked in snapshot_map (called from __split_and_process_bio)
SO you're saying the case that Neil doesn't think should happen:
https://lkml.org/lkml/2017/11/21/658
...can happen.
> > > The processing of md->rescued is also wrong - bios for different devices
> > > must be offloaded to different helper threads, so that processing a bio
> > > for a lower device doesn't depend on processing a bio for a higher device.
> > > If you offload all the bios on current->bio_list to the same thread, the
> > > bios still depend on each other and the deadlock will still happen.
> >
> > Commit 325738403 ("dm: revise 'rescue' strategy for bio-based bioset
> > allocations") speaks to this with:
> >
> > "Note that only current->bio_list[0] is offloaded. current->bio_list[1]
> > contains bios that were scheduled *before* the current one started, so
> > they must have been submitted from higher up the stack, and we cannot be
> > waiting for them here (thanks to the "dm: ensure bio submission follows
> > a depth-first tree walk" commit). Also, we now rescue *all* bios on the
> > list as there is nothing to be gained by being more selective."
>
> I think you are right - if we only offload current->bio_list[0], then
> mixing of dependent bios on the offloaded list won't happen.
>
> > And again: this patchset passes your dm-snapshot deadlock test. Is
> > that test somehow lacking?
>
> With your patchset, the deadlock would happen only if bios are queued on
> &md->deferred - and that happens only in case of resume or if we are
> processing REQ_PREFLUSH with non-zero data size.
>
> So, the simple test that I wrote doesn't trigger it, but a more complex
> test involving REQ_PREFLUSH could.
Makes sense. But I need to think further about _why_ bios submitted to
the snapshot driver's underlying device would end up on md->rescued
(like you suggested above). Again, Neil thinks it not possible. Neil
said:
"they will not be recursive calls, so nothing will be added to
current->bio_list[0] and nothing will be moved to md->rescued. Each
generic_make_request() will completely submit the request in the lower
level devel."
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-22 1:21 ` Mikulas Patocka
2017-11-22 2:32 ` Mike Snitzer
@ 2017-11-22 4:00 ` NeilBrown
2017-11-22 4:28 ` Mike Snitzer
2017-11-22 18:24 ` [dm-devel] " Mikulas Patocka
1 sibling, 2 replies; 22+ messages in thread
From: NeilBrown @ 2017-11-22 4:00 UTC (permalink / raw)
To: Mikulas Patocka, Mike Snitzer
Cc: Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Zdenek Kabelac
[-- Attachment #1: Type: text/plain, Size: 11093 bytes --]
On Tue, Nov 21 2017, Mikulas Patocka wrote:
> On Tue, 21 Nov 2017, Mike Snitzer wrote:
>
>> On Tue, Nov 21 2017 at 4:23pm -0500,
>> Mikulas Patocka <mpatocka@redhat.com> wrote:
>>
>> > This is not correct:
>> >
>> > 2206 static void dm_wq_work(struct work_struct *work)
>> > 2207 {
>> > 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
>> > 2209 struct bio *bio;
>> > 2210 int srcu_idx;
>> > 2211 struct dm_table *map;
>> > 2212
>> > 2213 if (!bio_list_empty(&md->rescued)) {
>> > 2214 struct bio_list list;
>> > 2215 spin_lock_irq(&md->deferred_lock);
>> > 2216 list = md->rescued;
>> > 2217 bio_list_init(&md->rescued);
>> > 2218 spin_unlock_irq(&md->deferred_lock);
>> > 2219 while ((bio = bio_list_pop(&list)))
>> > 2220 generic_make_request(bio);
>> > 2221 }
>> > 2222
>> > 2223 map = dm_get_live_table(md, &srcu_idx);
>> > 2224
>> > 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
>> > 2226 spin_lock_irq(&md->deferred_lock);
>> > 2227 bio = bio_list_pop(&md->deferred);
>> > 2228 spin_unlock_irq(&md->deferred_lock);
>> > 2229
>> > 2230 if (!bio)
>> > 2231 break;
>> > 2232
>> > 2233 if (dm_request_based(md))
>> > 2234 generic_make_request(bio);
>> > 2235 else
>> > 2236 __split_and_process_bio(md, map, bio);
>> > 2237 }
>> > 2238
>> > 2239 dm_put_live_table(md, srcu_idx);
>> > 2240 }
>> >
>> > You can see that if we are in dm_wq_work in __split_and_process_bio, we
>> > will not process md->rescued list.
>>
>> Can you elaborate further? We cannot be "in dm_wq_work in
>> __split_and_process_bio" simultaneously. Do you mean as a side-effect
>> of scheduling away from __split_and_process_bio?
>>
>> The more detail you can share the better.
>
> Suppose this scenario:
>
> * dm_wq_work calls __split_and_process_bio
> * __split_and_process_bio eventually reaches the function snapshot_map
> * snapshot_map attempts to take the snapshot lock
>
> * the snapshot lock could be released only if some bios submitted by the
> snapshot driver to the underlying device complete
> * the bios submitted to the underlying device were already offloaded by
> some other task and they are waiting on the list md->rescued
> * the bios waiting on md->rescued are not processed, because dm_wq_work is
> blocked in snapshot_map (called from __split_and_process_bio)
Yes, I think you are right.
I think the solution is to get rid of the dm_offload() infrastructure
and make it not necessary.
i.e. discard my patches
dm: prepare to discontinue use of BIOSET_NEED_RESCUER
and
dm: revise 'rescue' strategy for bio-based bioset allocations
And build on "dm: ensure bio submission follows a depth-first tree walk"
which was written after those and already makes dm_offload() less
important.
Since that "depth-first" patch, every request to the dm device, after
the initial splitting, allocates just one dm_target_io structure, and
makes just one __map_bio() call, and so will behave exactly the way
generic_make_request() expects and copes with - thus avoiding awkward
dependencies and deadlocks. Except....
a/ If any target defines ->num_write_bios() to return >1,
__clone_and_map_data_bio() will make multiple calls to alloc_tio()
and __map_bio(), which might need rescuing.
But no target defines num_write_bios, and none have since it was
removed from dm-cache 4.5 years ago.
Can we discard num_write_bios??
b/ If any target sets any of num_{flush,discard,write_same,write_zeroes}_bios
to a value > 1, then __send_duplicate_bios() will also make multiple
calls to alloc_tio() and __map_bio().
Some do.
dm-cache-target: flush=2
dm-snap: flush=2
dm-stripe: discard, write_same, write_zeroes all set to 'stripes'.
These will only be a problem if the second (or subsequent) alloc_tio()
blocks waiting for an earlier allocation to complete. This will only
be a problem if multiple threads are each trying to allocate multiple
dm_target_io from the same bioset at the same time.
This is rare and should be easier to address than the current
dm_offload() approach.
One possibility would be to copy the approach taken by
crypt_alloc_buffer() which needs to allocate multiple entries from a
mempool.
It first tries the with GFP_NOWAIT. If that fails it take a mutex and
tries with GFP_NOIO. This mean only one thread will try to allocate
multiple bios at once, so there can be no deadlock.
Below are two RFC patches. The first removes num_write_bios.
The second is incomplete and makes a stab are allocating multiple bios
at once safely.
A third would be needed to remove dm_offload() etc... but I cannot quite
fit that in today - must be off.
Thanks,
NeilBrown
From: NeilBrown <neilb@suse.com>
Date: Wed, 22 Nov 2017 14:25:18 +1100
Subject: [PATCH] DM: remove num_write_bios target interface.
No target provides num_write_bios and none has done
since 2013.
Having the possibility of num_write_bios > 1 complicates
bio allocation.
So remove the interface and assume there is only one bio
needed.
If a target ever needs more, it must provide a suitable
bioset and allocate itself based on its particular needs.
Signed-off-by: NeilBrown <neilb@suse.com>
---
drivers/md/dm.c | 22 ++++------------------
include/linux/device-mapper.h | 15 ---------------
2 files changed, 4 insertions(+), 33 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index b20febd6cbc7..8c1a05609eea 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1323,27 +1323,13 @@ static int __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti,
{
struct bio *bio = ci->bio;
struct dm_target_io *tio;
- unsigned target_bio_nr;
- unsigned num_target_bios = 1;
int r = 0;
- /*
- * Does the target want to receive duplicate copies of the bio?
- */
- if (bio_data_dir(bio) == WRITE && ti->num_write_bios)
- num_target_bios = ti->num_write_bios(ti, bio);
-
- for (target_bio_nr = 0; target_bio_nr < num_target_bios; target_bio_nr++) {
- tio = alloc_tio(ci, ti, target_bio_nr);
- tio->len_ptr = len;
- r = clone_bio(tio, bio, sector, *len);
- if (r < 0) {
- free_tio(tio);
- break;
- }
+ tio = alloc_tio(ci, ti, 0);
+ tio->len_ptr = len;
+ r = clone_bio(tio, bio, sector, *len);
+ if (r >= 0)
__map_bio(tio);
- }
-
return r;
}
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index a5538433c927..5a68b366e664 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -220,14 +220,6 @@ struct target_type {
#define DM_TARGET_WILDCARD 0x00000008
#define dm_target_is_wildcard(type) ((type)->features & DM_TARGET_WILDCARD)
-/*
- * Some targets need to be sent the same WRITE bio severals times so
- * that they can send copies of it to different devices. This function
- * examines any supplied bio and returns the number of copies of it the
- * target requires.
- */
-typedef unsigned (*dm_num_write_bios_fn) (struct dm_target *ti, struct bio *bio);
-
/*
* A target implements own bio data integrity.
*/
@@ -291,13 +283,6 @@ struct dm_target {
*/
unsigned per_io_data_size;
- /*
- * If defined, this function is called to find out how many
- * duplicate bios should be sent to the target when writing
- * data.
- */
- dm_num_write_bios_fn num_write_bios;
-
/* target specific data */
void *private;
--
2.14.0.rc0.dirty
-----------------------------------
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 8c1a05609eea..8762661df2ef 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1265,8 +1265,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
}
static struct dm_target_io *alloc_tio(struct clone_info *ci,
- struct dm_target *ti,
- unsigned target_bio_nr)
+ struct dm_target *ti)
{
struct dm_target_io *tio;
struct bio *clone;
@@ -1276,34 +1275,66 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci,
tio->io = ci->io;
tio->ti = ti;
- tio->target_bio_nr = target_bio_nr;
+ tio->target_bio_nr = 0;
return tio;
}
-static void __clone_and_map_simple_bio(struct clone_info *ci,
- struct dm_target *ti,
- unsigned target_bio_nr, unsigned *len)
+static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
+ struct dm_target *ti, unsigned num_bios)
{
- struct dm_target_io *tio = alloc_tio(ci, ti, target_bio_nr);
- struct bio *clone = &tio->clone;
+ int try;
- tio->len_ptr = len;
+ for (try = 0; try < 2; try++) {
+ int bio_nr;
+ struct bio *bio;
+
+ if (try)
+ mutex_lock(&ci->md->table_devices_lock);
+ for (bio_nr = 0; bio_nr < num_bios; bio_nr++) {
+ bio = bio_alloc_bioset(try ? GFP_NOIO : GFP_NOWAIT,
+ 0, ci->md->bs);
+ if (bio) {
+ struct dm_target_io *tio;
+ bio_list_add(blist, bio);
+ tio = container_of(bio, struct dm_target_io, clone);
- __bio_clone_fast(clone, ci->bio);
- if (len)
- bio_setup_sector(clone, ci->sector, *len);
+ tio->io = ci->io;
+ tio->ti = ti;
+ tio->target_bio_nr = bio_nr;
+ } else
+ break;
+ }
+ if (try)
+ mutex_unlock(&ci->md->table_devices_lock);
+ if (bio_nr == num_bios)
+ return;
- __map_bio(tio);
+ while ((bio = bio_list_pop(blist)) != NULL)
+ bio_put(bio);
+ }
}
static void __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
unsigned num_bios, unsigned *len)
{
- unsigned target_bio_nr;
+ struct bio_list blist = BIO_EMPTY_LIST;
+ struct bio *bio;
- for (target_bio_nr = 0; target_bio_nr < num_bios; target_bio_nr++)
- __clone_and_map_simple_bio(ci, ti, target_bio_nr, len);
+ if (num_bios == 1)
+ bio_list_add(&blist, &alloc_tio(ci, ti)->clone);
+ else
+ alloc_multiple_bios(&blist, ci, ti, num_bios);
+
+ while ((bio = bio_list_pop(&blist)) != NULL) {
+ struct dm_target_io *tio = container_of(
+ bio, struct dm_target_io, clone);
+ tio->len_ptr = len;
+ __bio_clone_fast(bio, ci->bio);
+ if (len)
+ bio_setup_sector(bio, ci->sector, *len);
+ __map_bio(tio);
+ }
}
static int __send_empty_flush(struct clone_info *ci)
@@ -1325,7 +1356,7 @@ static int __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti,
struct dm_target_io *tio;
int r = 0;
- tio = alloc_tio(ci, ti, 0);
+ tio = alloc_tio(ci, ti);
tio->len_ptr = len;
r = clone_bio(tio, bio, sector, *len);
if (r >= 0)
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-22 4:00 ` [dm-devel] " NeilBrown
@ 2017-11-22 4:28 ` Mike Snitzer
2017-11-22 21:18 ` Mike Snitzer
2017-11-22 18:24 ` [dm-devel] " Mikulas Patocka
1 sibling, 1 reply; 22+ messages in thread
From: Mike Snitzer @ 2017-11-22 4:28 UTC (permalink / raw)
To: NeilBrown
Cc: Mikulas Patocka, Jens Axboe, linux-kernel@vger.kernel.org,
linux-block, device-mapper development, Zdenek Kabelac
On Tue, Nov 21 2017 at 11:00pm -0500,
NeilBrown <neilb@suse.com> wrote:
> On Tue, Nov 21 2017, Mikulas Patocka wrote:
>
> > On Tue, 21 Nov 2017, Mike Snitzer wrote:
> >
> >> On Tue, Nov 21 2017 at 4:23pm -0500,
> >> Mikulas Patocka <mpatocka@redhat.com> wrote:
> >>
> >> > This is not correct:
> >> >
> >> > 2206 static void dm_wq_work(struct work_struct *work)
> >> > 2207 {
> >> > 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
> >> > 2209 struct bio *bio;
> >> > 2210 int srcu_idx;
> >> > 2211 struct dm_table *map;
> >> > 2212
> >> > 2213 if (!bio_list_empty(&md->rescued)) {
> >> > 2214 struct bio_list list;
> >> > 2215 spin_lock_irq(&md->deferred_lock);
> >> > 2216 list = md->rescued;
> >> > 2217 bio_list_init(&md->rescued);
> >> > 2218 spin_unlock_irq(&md->deferred_lock);
> >> > 2219 while ((bio = bio_list_pop(&list)))
> >> > 2220 generic_make_request(bio);
> >> > 2221 }
> >> > 2222
> >> > 2223 map = dm_get_live_table(md, &srcu_idx);
> >> > 2224
> >> > 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
> >> > 2226 spin_lock_irq(&md->deferred_lock);
> >> > 2227 bio = bio_list_pop(&md->deferred);
> >> > 2228 spin_unlock_irq(&md->deferred_lock);
> >> > 2229
> >> > 2230 if (!bio)
> >> > 2231 break;
> >> > 2232
> >> > 2233 if (dm_request_based(md))
> >> > 2234 generic_make_request(bio);
> >> > 2235 else
> >> > 2236 __split_and_process_bio(md, map, bio);
> >> > 2237 }
> >> > 2238
> >> > 2239 dm_put_live_table(md, srcu_idx);
> >> > 2240 }
> >> >
> >> > You can see that if we are in dm_wq_work in __split_and_process_bio, we
> >> > will not process md->rescued list.
> >>
> >> Can you elaborate further? We cannot be "in dm_wq_work in
> >> __split_and_process_bio" simultaneously. Do you mean as a side-effect
> >> of scheduling away from __split_and_process_bio?
> >>
> >> The more detail you can share the better.
> >
> > Suppose this scenario:
> >
> > * dm_wq_work calls __split_and_process_bio
> > * __split_and_process_bio eventually reaches the function snapshot_map
> > * snapshot_map attempts to take the snapshot lock
> >
> > * the snapshot lock could be released only if some bios submitted by the
> > snapshot driver to the underlying device complete
> > * the bios submitted to the underlying device were already offloaded by
> > some other task and they are waiting on the list md->rescued
> > * the bios waiting on md->rescued are not processed, because dm_wq_work is
> > blocked in snapshot_map (called from __split_and_process_bio)
>
> Yes, I think you are right.
>
> I think the solution is to get rid of the dm_offload() infrastructure
> and make it not necessary.
> i.e. discard my patches
> dm: prepare to discontinue use of BIOSET_NEED_RESCUER
> and
> dm: revise 'rescue' strategy for bio-based bioset allocations
>
> And build on "dm: ensure bio submission follows a depth-first tree walk"
> which was written after those and already makes dm_offload() less
> important.
>
> Since that "depth-first" patch, every request to the dm device, after
> the initial splitting, allocates just one dm_target_io structure, and
> makes just one __map_bio() call, and so will behave exactly the way
> generic_make_request() expects and copes with - thus avoiding awkward
> dependencies and deadlocks. Except....
Yes, FYI I've also verified that even with just the "depth-first" patch
(and dm_offload disabled) the snapshot deadlock is fixed.
> a/ If any target defines ->num_write_bios() to return >1,
> __clone_and_map_data_bio() will make multiple calls to alloc_tio()
> and __map_bio(), which might need rescuing.
> But no target defines num_write_bios, and none have since it was
> removed from dm-cache 4.5 years ago.
> Can we discard num_write_bios??
Yes.
> b/ If any target sets any of num_{flush,discard,write_same,write_zeroes}_bios
> to a value > 1, then __send_duplicate_bios() will also make multiple
> calls to alloc_tio() and __map_bio().
> Some do.
> dm-cache-target: flush=2
> dm-snap: flush=2
> dm-stripe: discard, write_same, write_zeroes all set to 'stripes'.
>
> These will only be a problem if the second (or subsequent) alloc_tio()
> blocks waiting for an earlier allocation to complete. This will only
> be a problem if multiple threads are each trying to allocate multiple
> dm_target_io from the same bioset at the same time.
> This is rare and should be easier to address than the current
> dm_offload() approach.
> One possibility would be to copy the approach taken by
> crypt_alloc_buffer() which needs to allocate multiple entries from a
> mempool.
> It first tries the with GFP_NOWAIT. If that fails it take a mutex and
> tries with GFP_NOIO. This mean only one thread will try to allocate
> multiple bios at once, so there can be no deadlock.
>
> Below are two RFC patches. The first removes num_write_bios.
> The second is incomplete and makes a stab are allocating multiple bios
> at once safely.
> A third would be needed to remove dm_offload() etc... but I cannot quite
> fit that in today - must be off.
Great.
> From: NeilBrown <neilb@suse.com>
> Date: Wed, 22 Nov 2017 14:25:18 +1100
> Subject: [PATCH] DM: remove num_write_bios target interface.
>
> No target provides num_write_bios and none has done
> since 2013.
> Having the possibility of num_write_bios > 1 complicates
> bio allocation.
> So remove the interface and assume there is only one bio
> needed.
> If a target ever needs more, it must provide a suitable
> bioset and allocate itself based on its particular needs.
>
> Signed-off-by: NeilBrown <neilb@suse.com>
> ---
> drivers/md/dm.c | 22 ++++------------------
> include/linux/device-mapper.h | 15 ---------------
> 2 files changed, 4 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index b20febd6cbc7..8c1a05609eea 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -1323,27 +1323,13 @@ static int __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti,
> {
> struct bio *bio = ci->bio;
> struct dm_target_io *tio;
> - unsigned target_bio_nr;
> - unsigned num_target_bios = 1;
> int r = 0;
>
> - /*
> - * Does the target want to receive duplicate copies of the bio?
> - */
> - if (bio_data_dir(bio) == WRITE && ti->num_write_bios)
> - num_target_bios = ti->num_write_bios(ti, bio);
> -
> - for (target_bio_nr = 0; target_bio_nr < num_target_bios; target_bio_nr++) {
> - tio = alloc_tio(ci, ti, target_bio_nr);
> - tio->len_ptr = len;
> - r = clone_bio(tio, bio, sector, *len);
> - if (r < 0) {
> - free_tio(tio);
> - break;
> - }
> + tio = alloc_tio(ci, ti, 0);
> + tio->len_ptr = len;
> + r = clone_bio(tio, bio, sector, *len);
> + if (r >= 0)
> __map_bio(tio);
> - }
> -
This bit is wrong, free_tio() is needed if clone_bio() fails. I can fix
it up though.
I'll work through your patches tomorrow.
Thanks,
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-22 4:00 ` [dm-devel] " NeilBrown
2017-11-22 4:28 ` Mike Snitzer
@ 2017-11-22 18:24 ` Mikulas Patocka
2017-11-22 18:49 ` Mike Snitzer
` (2 more replies)
1 sibling, 3 replies; 22+ messages in thread
From: Mikulas Patocka @ 2017-11-22 18:24 UTC (permalink / raw)
To: NeilBrown
Cc: Mike Snitzer, Jens Axboe, linux-kernel@vger.kernel.org,
linux-block, device-mapper development, Zdenek Kabelac
On Wed, 22 Nov 2017, NeilBrown wrote:
> On Tue, Nov 21 2017, Mikulas Patocka wrote:
>
> > On Tue, 21 Nov 2017, Mike Snitzer wrote:
> >
> >> On Tue, Nov 21 2017 at 4:23pm -0500,
> >> Mikulas Patocka <mpatocka@redhat.com> wrote:
> >>
> >> > This is not correct:
> >> >
> >> > 2206 static void dm_wq_work(struct work_struct *work)
> >> > 2207 {
> >> > 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
> >> > 2209 struct bio *bio;
> >> > 2210 int srcu_idx;
> >> > 2211 struct dm_table *map;
> >> > 2212
> >> > 2213 if (!bio_list_empty(&md->rescued)) {
> >> > 2214 struct bio_list list;
> >> > 2215 spin_lock_irq(&md->deferred_lock);
> >> > 2216 list = md->rescued;
> >> > 2217 bio_list_init(&md->rescued);
> >> > 2218 spin_unlock_irq(&md->deferred_lock);
> >> > 2219 while ((bio = bio_list_pop(&list)))
> >> > 2220 generic_make_request(bio);
> >> > 2221 }
> >> > 2222
> >> > 2223 map = dm_get_live_table(md, &srcu_idx);
> >> > 2224
> >> > 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
> >> > 2226 spin_lock_irq(&md->deferred_lock);
> >> > 2227 bio = bio_list_pop(&md->deferred);
> >> > 2228 spin_unlock_irq(&md->deferred_lock);
> >> > 2229
> >> > 2230 if (!bio)
> >> > 2231 break;
> >> > 2232
> >> > 2233 if (dm_request_based(md))
> >> > 2234 generic_make_request(bio);
> >> > 2235 else
> >> > 2236 __split_and_process_bio(md, map, bio);
> >> > 2237 }
> >> > 2238
> >> > 2239 dm_put_live_table(md, srcu_idx);
> >> > 2240 }
> >> >
> >> > You can see that if we are in dm_wq_work in __split_and_process_bio, we
> >> > will not process md->rescued list.
> >>
> >> Can you elaborate further? We cannot be "in dm_wq_work in
> >> __split_and_process_bio" simultaneously. Do you mean as a side-effect
> >> of scheduling away from __split_and_process_bio?
> >>
> >> The more detail you can share the better.
> >
> > Suppose this scenario:
> >
> > * dm_wq_work calls __split_and_process_bio
> > * __split_and_process_bio eventually reaches the function snapshot_map
> > * snapshot_map attempts to take the snapshot lock
> >
> > * the snapshot lock could be released only if some bios submitted by the
> > snapshot driver to the underlying device complete
> > * the bios submitted to the underlying device were already offloaded by
> > some other task and they are waiting on the list md->rescued
> > * the bios waiting on md->rescued are not processed, because dm_wq_work is
> > blocked in snapshot_map (called from __split_and_process_bio)
>
> Yes, I think you are right.
>
> I think the solution is to get rid of the dm_offload() infrastructure
> and make it not necessary.
> i.e. discard my patches
> dm: prepare to discontinue use of BIOSET_NEED_RESCUER
> and
> dm: revise 'rescue' strategy for bio-based bioset allocations
>
> And build on "dm: ensure bio submission follows a depth-first tree walk"
> which was written after those and already makes dm_offload() less
> important.
>
> Since that "depth-first" patch, every request to the dm device, after
> the initial splitting, allocates just one dm_target_io structure, and
> makes just one __map_bio() call, and so will behave exactly the way
> generic_make_request() expects and copes with - thus avoiding awkward
> dependencies and deadlocks. Except....
>
> a/ If any target defines ->num_write_bios() to return >1,
> __clone_and_map_data_bio() will make multiple calls to alloc_tio()
> and __map_bio(), which might need rescuing.
> But no target defines num_write_bios, and none have since it was
> removed from dm-cache 4.5 years ago.
> Can we discard num_write_bios??
>
> b/ If any target sets any of num_{flush,discard,write_same,write_zeroes}_bios
> to a value > 1, then __send_duplicate_bios() will also make multiple
> calls to alloc_tio() and __map_bio().
> Some do.
> dm-cache-target: flush=2
> dm-snap: flush=2
> dm-stripe: discard, write_same, write_zeroes all set to 'stripes'.
>
> These will only be a problem if the second (or subsequent) alloc_tio()
> blocks waiting for an earlier allocation to complete. This will only
> be a problem if multiple threads are each trying to allocate multiple
> dm_target_io from the same bioset at the same time.
> This is rare and should be easier to address than the current
> dm_offload() approach.
> One possibility would be to copy the approach taken by
> crypt_alloc_buffer() which needs to allocate multiple entries from a
> mempool.
> It first tries the with GFP_NOWAIT. If that fails it take a mutex and
> tries with GFP_NOIO. This mean only one thread will try to allocate
> multiple bios at once, so there can be no deadlock.
>
> Below are two RFC patches. The first removes num_write_bios.
> The second is incomplete and makes a stab are allocating multiple bios
> at once safely.
> A third would be needed to remove dm_offload() etc... but I cannot quite
> fit that in today - must be off.
>
> Thanks,
> NeilBrown
Another problem is this:
struct bio *b = bio_clone_bioset(bio, GFP_NOIO, md->queue->bio_split);
bio_advance(b, (bio_sectors(b) - ci.sector_count) << 9);
bio_chain(b, bio);
What if it blocks because the bioset is exhausted?
The code basically builds a chain of bios of unlimited length (suppose for
example a case when we are splitting on every sector boundary, so there
will be one bio for every sector in the original bio), it could exhaust
the bioset easily.
It would be better to use mechanism from md-raid that chains all the
sub-bios to the same master bio and doesn't create long chains of bios:
if (max_sectors < bio_sectors(bio)) {
struct bio *split = bio_split(bio, max_sectors,
gfp, conf->bio_split);
bio_chain(split, bio);
generic_make_request(bio);
bio = split;
r1_bio->master_bio = bio;
r1_bio->sectors = max_sectors;
}
Mikulas
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-22 18:24 ` [dm-devel] " Mikulas Patocka
@ 2017-11-22 18:49 ` Mike Snitzer
2017-11-23 5:12 ` [dm-devel] " NeilBrown
2017-11-23 22:52 ` [PATCH] dm: use cloned bio as head, not remainder, in __split_and_process_bio() NeilBrown
2 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2017-11-22 18:49 UTC (permalink / raw)
To: Mikulas Patocka
Cc: NeilBrown, Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Zdenek Kabelac
On Wed, Nov 22 2017 at 1:24pm -0500,
Mikulas Patocka <mpatocka@redhat.com> wrote:
> Another problem is this:
>
> struct bio *b = bio_clone_bioset(bio, GFP_NOIO, md->queue->bio_split);
> bio_advance(b, (bio_sectors(b) - ci.sector_count) << 9);
> bio_chain(b, bio);
>
> What if it blocks because the bioset is exhausted?
>
> The code basically builds a chain of bios of unlimited length (suppose for
> example a case when we are splitting on every sector boundary, so there
> will be one bio for every sector in the original bio), it could exhaust
> the bioset easily.
>
> It would be better to use mechanism from md-raid that chains all the
> sub-bios to the same master bio and doesn't create long chains of bios:
>
> if (max_sectors < bio_sectors(bio)) {
> struct bio *split = bio_split(bio, max_sectors,
> gfp, conf->bio_split);
> bio_chain(split, bio);
> generic_make_request(bio);
> bio = split;
> r1_bio->master_bio = bio;
> r1_bio->sectors = max_sectors;
> }
I'd be happy to take an incremental patch that improves on this commit:
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.16&id=b46d6a08f1ae7bf53e4cde28e0ccdf91567d432e
But short of that I'll have to come back to this.
Thanks,
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-22 4:28 ` Mike Snitzer
@ 2017-11-22 21:18 ` Mike Snitzer
0 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2017-11-22 21:18 UTC (permalink / raw)
To: NeilBrown
Cc: Mikulas Patocka, Jens Axboe, linux-kernel@vger.kernel.org,
linux-block, device-mapper development, Zdenek Kabelac
On Tue, Nov 21 2017 at 11:28pm -0500,
Mike Snitzer <snitzer@redhat.com> wrote:
>
> I'll work through your patches tomorrow.
Please see the top 3 patches on this branch:
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/log/?h=dm-4.16
This rebased dm-4.16 branch seems to be working well so far.
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER
2017-11-22 18:24 ` [dm-devel] " Mikulas Patocka
2017-11-22 18:49 ` Mike Snitzer
@ 2017-11-23 5:12 ` NeilBrown
2017-11-23 22:52 ` [PATCH] dm: use cloned bio as head, not remainder, in __split_and_process_bio() NeilBrown
2 siblings, 0 replies; 22+ messages in thread
From: NeilBrown @ 2017-11-23 5:12 UTC (permalink / raw)
To: Mikulas Patocka
Cc: Mike Snitzer, Jens Axboe, linux-kernel@vger.kernel.org,
linux-block, device-mapper development, Zdenek Kabelac
[-- Attachment #1: Type: text/plain, Size: 7367 bytes --]
On Wed, Nov 22 2017, Mikulas Patocka wrote:
> On Wed, 22 Nov 2017, NeilBrown wrote:
>
>> On Tue, Nov 21 2017, Mikulas Patocka wrote:
>>
>> > On Tue, 21 Nov 2017, Mike Snitzer wrote:
>> >
>> >> On Tue, Nov 21 2017 at 4:23pm -0500,
>> >> Mikulas Patocka <mpatocka@redhat.com> wrote:
>> >>
>> >> > This is not correct:
>> >> >
>> >> > 2206 static void dm_wq_work(struct work_struct *work)
>> >> > 2207 {
>> >> > 2208 struct mapped_device *md = container_of(work, struct mapped_device, work);
>> >> > 2209 struct bio *bio;
>> >> > 2210 int srcu_idx;
>> >> > 2211 struct dm_table *map;
>> >> > 2212
>> >> > 2213 if (!bio_list_empty(&md->rescued)) {
>> >> > 2214 struct bio_list list;
>> >> > 2215 spin_lock_irq(&md->deferred_lock);
>> >> > 2216 list = md->rescued;
>> >> > 2217 bio_list_init(&md->rescued);
>> >> > 2218 spin_unlock_irq(&md->deferred_lock);
>> >> > 2219 while ((bio = bio_list_pop(&list)))
>> >> > 2220 generic_make_request(bio);
>> >> > 2221 }
>> >> > 2222
>> >> > 2223 map = dm_get_live_table(md, &srcu_idx);
>> >> > 2224
>> >> > 2225 while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
>> >> > 2226 spin_lock_irq(&md->deferred_lock);
>> >> > 2227 bio = bio_list_pop(&md->deferred);
>> >> > 2228 spin_unlock_irq(&md->deferred_lock);
>> >> > 2229
>> >> > 2230 if (!bio)
>> >> > 2231 break;
>> >> > 2232
>> >> > 2233 if (dm_request_based(md))
>> >> > 2234 generic_make_request(bio);
>> >> > 2235 else
>> >> > 2236 __split_and_process_bio(md, map, bio);
>> >> > 2237 }
>> >> > 2238
>> >> > 2239 dm_put_live_table(md, srcu_idx);
>> >> > 2240 }
>> >> >
>> >> > You can see that if we are in dm_wq_work in __split_and_process_bio, we
>> >> > will not process md->rescued list.
>> >>
>> >> Can you elaborate further? We cannot be "in dm_wq_work in
>> >> __split_and_process_bio" simultaneously. Do you mean as a side-effect
>> >> of scheduling away from __split_and_process_bio?
>> >>
>> >> The more detail you can share the better.
>> >
>> > Suppose this scenario:
>> >
>> > * dm_wq_work calls __split_and_process_bio
>> > * __split_and_process_bio eventually reaches the function snapshot_map
>> > * snapshot_map attempts to take the snapshot lock
>> >
>> > * the snapshot lock could be released only if some bios submitted by the
>> > snapshot driver to the underlying device complete
>> > * the bios submitted to the underlying device were already offloaded by
>> > some other task and they are waiting on the list md->rescued
>> > * the bios waiting on md->rescued are not processed, because dm_wq_work is
>> > blocked in snapshot_map (called from __split_and_process_bio)
>>
>> Yes, I think you are right.
>>
>> I think the solution is to get rid of the dm_offload() infrastructure
>> and make it not necessary.
>> i.e. discard my patches
>> dm: prepare to discontinue use of BIOSET_NEED_RESCUER
>> and
>> dm: revise 'rescue' strategy for bio-based bioset allocations
>>
>> And build on "dm: ensure bio submission follows a depth-first tree walk"
>> which was written after those and already makes dm_offload() less
>> important.
>>
>> Since that "depth-first" patch, every request to the dm device, after
>> the initial splitting, allocates just one dm_target_io structure, and
>> makes just one __map_bio() call, and so will behave exactly the way
>> generic_make_request() expects and copes with - thus avoiding awkward
>> dependencies and deadlocks. Except....
>>
>> a/ If any target defines ->num_write_bios() to return >1,
>> __clone_and_map_data_bio() will make multiple calls to alloc_tio()
>> and __map_bio(), which might need rescuing.
>> But no target defines num_write_bios, and none have since it was
>> removed from dm-cache 4.5 years ago.
>> Can we discard num_write_bios??
>>
>> b/ If any target sets any of num_{flush,discard,write_same,write_zeroes}_bios
>> to a value > 1, then __send_duplicate_bios() will also make multiple
>> calls to alloc_tio() and __map_bio().
>> Some do.
>> dm-cache-target: flush=2
>> dm-snap: flush=2
>> dm-stripe: discard, write_same, write_zeroes all set to 'stripes'.
>>
>> These will only be a problem if the second (or subsequent) alloc_tio()
>> blocks waiting for an earlier allocation to complete. This will only
>> be a problem if multiple threads are each trying to allocate multiple
>> dm_target_io from the same bioset at the same time.
>> This is rare and should be easier to address than the current
>> dm_offload() approach.
>> One possibility would be to copy the approach taken by
>> crypt_alloc_buffer() which needs to allocate multiple entries from a
>> mempool.
>> It first tries the with GFP_NOWAIT. If that fails it take a mutex and
>> tries with GFP_NOIO. This mean only one thread will try to allocate
>> multiple bios at once, so there can be no deadlock.
>>
>> Below are two RFC patches. The first removes num_write_bios.
>> The second is incomplete and makes a stab are allocating multiple bios
>> at once safely.
>> A third would be needed to remove dm_offload() etc... but I cannot quite
>> fit that in today - must be off.
>>
>> Thanks,
>> NeilBrown
>
> Another problem is this:
>
> struct bio *b = bio_clone_bioset(bio, GFP_NOIO, md->queue->bio_split);
> bio_advance(b, (bio_sectors(b) - ci.sector_count) << 9);
> bio_chain(b, bio);
>
> What if it blocks because the bioset is exhausted?
>
> The code basically builds a chain of bios of unlimited length (suppose for
> example a case when we are splitting on every sector boundary, so there
> will be one bio for every sector in the original bio), it could exhaust
> the bioset easily.
>
> It would be better to use mechanism from md-raid that chains all the
> sub-bios to the same master bio and doesn't create long chains of bios:
>
> if (max_sectors < bio_sectors(bio)) {
> struct bio *split = bio_split(bio, max_sectors,
> gfp, conf->bio_split);
> bio_chain(split, bio);
> generic_make_request(bio);
> bio = split;
> r1_bio->master_bio = bio;
> r1_bio->sectors = max_sectors;
> }
>
> Mikulas
Yes, you are right something like that would be better.
Also send_changing_extent_only allocates bios in a loop which can cause
problems.
I think we need to get __split_and_process_non_flush(), in all its
branches, to check if len is too large for a single request, and if it
is, create a clone for the prefix, attached that to the ci and map it,
advance the original bio, and call generic_make_request on it.
That shouldn't be too hard, but it is a change that would touch a few
places.
I'll see if I can write something.
Thanks,
NeilBrown
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH] dm: use cloned bio as head, not remainder, in __split_and_process_bio()
2017-11-22 18:24 ` [dm-devel] " Mikulas Patocka
2017-11-22 18:49 ` Mike Snitzer
2017-11-23 5:12 ` [dm-devel] " NeilBrown
@ 2017-11-23 22:52 ` NeilBrown
2017-11-27 14:23 ` Mike Snitzer
2 siblings, 1 reply; 22+ messages in thread
From: NeilBrown @ 2017-11-23 22:52 UTC (permalink / raw)
To: Mikulas Patocka
Cc: Mike Snitzer, Jens Axboe, linux-kernel@vger.kernel.org,
linux-block, device-mapper development, Zdenek Kabelac
[-- Attachment #1: Type: text/plain, Size: 2559 bytes --]
When we use bio_clone_bioset() to split off the front part of a bio
and chain the two together and submit the remainder to
generic_make_request(), it is important that the newly allocated
bio is used as the head to be processed immediately, and the original
bio gets "bio_advance()"d and sent to generic_make_request() as the
remainder.
If the newly allocated bio is used as the remainder, and if it then
needs to be split again, then the next bio_clone_bioset() call will
be made while holding a reference a bio (result of the first clone)
from the same bioset. This can potentially exhaust the bioset mempool
and result in a memory allocation deadlock.
So the result of the bio_clone_bioset() must be attached to the new
dm_io struct, and the original must be resubmitted. The current code
is backwards.
Note that there is no race caused by reassigning cio.io->bio after already
calling __map_bio(). This bio will only be dereferenced again after
dec_pending() has found io->io_count to be zero, and this cannot happen
before the dec_pending() call at the end of __split_and_process_bio().
Reported-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.com>
---
Hi,
I think this should resolve the problem Mikulas noticed that the
bios form a deep chain instead of a wide tree.
Thanks,
NeilBrown
drivers/md/dm.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 99ec215f7dcb..2e0e10a1c030 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1482,12 +1482,19 @@ static void __split_and_process_bio(struct mapped_device *md,
* Remainder must be passed to generic_make_request()
* so that it gets handled *after* bios already submitted
* have been completely processed.
+ * We take a clone of the original to store in
+ * ci.io->bio to be used by end_io_acct() and
+ * for dec_pending to use for completion handling.
+ * As this path is not used for REQ_OP_ZONE_REPORT,
+ * the usage of io->bio in dm_remap_zone_report()
+ * won't be affected by this reassignment.
*/
struct bio *b = bio_clone_bioset(bio, GFP_NOIO,
md->queue->bio_split);
- bio_advance(b, (bio_sectors(b) - ci.sector_count) << 9);
+ ci.io->bio = b;
+ bio_advance(bio, (bio_sectors(bio) - ci.sector_count) << 9);
bio_chain(b, bio);
- generic_make_request(b);
+ generic_make_request(bio);
break;
}
}
--
2.14.0.rc0.dirty
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: dm: use cloned bio as head, not remainder, in __split_and_process_bio()
2017-11-23 22:52 ` [PATCH] dm: use cloned bio as head, not remainder, in __split_and_process_bio() NeilBrown
@ 2017-11-27 14:23 ` Mike Snitzer
2017-11-28 22:18 ` [dm-devel] " NeilBrown
0 siblings, 1 reply; 22+ messages in thread
From: Mike Snitzer @ 2017-11-27 14:23 UTC (permalink / raw)
To: NeilBrown
Cc: Mikulas Patocka, Jens Axboe, linux-kernel@vger.kernel.org,
linux-block, device-mapper development, Zdenek Kabelac
On Thu, Nov 23 2017 at 5:52pm -0500,
NeilBrown <neilb@suse.com> wrote:
>
> When we use bio_clone_bioset() to split off the front part of a bio
> and chain the two together and submit the remainder to
> generic_make_request(), it is important that the newly allocated
> bio is used as the head to be processed immediately, and the original
> bio gets "bio_advance()"d and sent to generic_make_request() as the
> remainder.
>
> If the newly allocated bio is used as the remainder, and if it then
> needs to be split again, then the next bio_clone_bioset() call will
> be made while holding a reference a bio (result of the first clone)
> from the same bioset. This can potentially exhaust the bioset mempool
> and result in a memory allocation deadlock.
>
> So the result of the bio_clone_bioset() must be attached to the new
> dm_io struct, and the original must be resubmitted. The current code
> is backwards.
>
> Note that there is no race caused by reassigning cio.io->bio after already
> calling __map_bio(). This bio will only be dereferenced again after
> dec_pending() has found io->io_count to be zero, and this cannot happen
> before the dec_pending() call at the end of __split_and_process_bio().
>
> Reported-by: Mikulas Patocka <mpatocka@redhat.com>
> Signed-off-by: NeilBrown <neilb@suse.com>
> ---
>
> Hi,
> I think this should resolve the problem Mikulas noticed that the
> bios form a deep chain instead of a wide tree.
I'm inclined to just fold this into the original commit.
I'd update that header to make mention of the details captured in this
header.
Would you be OK with that?
Mike
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [dm-devel] dm: use cloned bio as head, not remainder, in __split_and_process_bio()
2017-11-27 14:23 ` Mike Snitzer
@ 2017-11-28 22:18 ` NeilBrown
0 siblings, 0 replies; 22+ messages in thread
From: NeilBrown @ 2017-11-28 22:18 UTC (permalink / raw)
To: Mike Snitzer
Cc: Jens Axboe, linux-kernel@vger.kernel.org, linux-block,
device-mapper development, Mikulas Patocka, Zdenek Kabelac
[-- Attachment #1: Type: text/plain, Size: 1802 bytes --]
On Mon, Nov 27 2017, Mike Snitzer wrote:
> On Thu, Nov 23 2017 at 5:52pm -0500,
> NeilBrown <neilb@suse.com> wrote:
>
>>
>> When we use bio_clone_bioset() to split off the front part of a bio
>> and chain the two together and submit the remainder to
>> generic_make_request(), it is important that the newly allocated
>> bio is used as the head to be processed immediately, and the original
>> bio gets "bio_advance()"d and sent to generic_make_request() as the
>> remainder.
>>
>> If the newly allocated bio is used as the remainder, and if it then
>> needs to be split again, then the next bio_clone_bioset() call will
>> be made while holding a reference a bio (result of the first clone)
>> from the same bioset. This can potentially exhaust the bioset mempool
>> and result in a memory allocation deadlock.
>>
>> So the result of the bio_clone_bioset() must be attached to the new
>> dm_io struct, and the original must be resubmitted. The current code
>> is backwards.
>>
>> Note that there is no race caused by reassigning cio.io->bio after already
>> calling __map_bio(). This bio will only be dereferenced again after
>> dec_pending() has found io->io_count to be zero, and this cannot happen
>> before the dec_pending() call at the end of __split_and_process_bio().
>>
>> Reported-by: Mikulas Patocka <mpatocka@redhat.com>
>> Signed-off-by: NeilBrown <neilb@suse.com>
>> ---
>>
>> Hi,
>> I think this should resolve the problem Mikulas noticed that the
>> bios form a deep chain instead of a wide tree.
>
> I'm inclined to just fold this into the original commit.
> I'd update that header to make mention of the details captured in this
> header.
>
> Would you be OK with that?
Perfectly OK with that. Thanks for asking.
NeilBrown
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2017-11-28 22:18 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <149776047907.23258.8058071140236879834.stgit@noble>
[not found] ` <20170618184143.GA10920@kernel.dk>
[not found] ` <87poe13rmm.fsf@notabene.neil.brown.name>
2017-11-20 16:43 ` [PATCH 00/13] block: assorted cleanup for bio splitting and cloning Mike Snitzer
2017-11-21 0:34 ` [dm-devel] " NeilBrown
2017-11-21 1:35 ` Mike Snitzer
2017-11-21 12:10 ` Mike Snitzer
2017-11-21 12:43 ` Mike Snitzer
2017-11-21 19:47 ` new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.] Mike Snitzer
2017-11-21 21:23 ` [dm-devel] " Mikulas Patocka
2017-11-21 22:51 ` new patchset to eliminate DM's use of BIOSET_NEED_RESCUER Mike Snitzer
2017-11-22 1:21 ` Mikulas Patocka
2017-11-22 2:32 ` Mike Snitzer
2017-11-22 4:00 ` [dm-devel] " NeilBrown
2017-11-22 4:28 ` Mike Snitzer
2017-11-22 21:18 ` Mike Snitzer
2017-11-22 18:24 ` [dm-devel] " Mikulas Patocka
2017-11-22 18:49 ` Mike Snitzer
2017-11-23 5:12 ` [dm-devel] " NeilBrown
2017-11-23 22:52 ` [PATCH] dm: use cloned bio as head, not remainder, in __split_and_process_bio() NeilBrown
2017-11-27 14:23 ` Mike Snitzer
2017-11-28 22:18 ` [dm-devel] " NeilBrown
2017-11-21 23:03 ` [dm-devel] new patchset to eliminate DM's use of BIOSET_NEED_RESCUER [was: Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.] NeilBrown
2017-11-21 19:44 ` [dm-devel] [PATCH 00/13] block: assorted cleanup for bio splitting and cloning NeilBrown
2017-11-21 19:50 ` Mike Snitzer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox