All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] dm-raid: unsynced raid snapshot creation/deletion causes panic (work queue teardown race)
@ 2015-04-29 12:33 heinzm
  2015-05-11 20:30 ` Mike Snitzer
  0 siblings, 1 reply; 3+ messages in thread
From: heinzm @ 2015-04-29 12:33 UTC (permalink / raw)
  To: dm-devel; +Cc: Heinz Mauelshagen

From: Heinz Mauelshagen <heinzm@redhat.com>

This patch avoids oopses caused by a callback racing
with the destrution of a mapping.


Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
Tested-by: Heinz Mauelshagen <heinzm@redhat.com>


---
 drivers/md/dm-raid.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 88e4c7f..fc4bc83 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1614,6 +1614,17 @@ static void raid_presuspend(struct dm_target *ti)
 {
 	struct raid_set *rs = ti->private;
 
+	/*
+	 * Address a teardown race when calling
+	 * raid_(pre|post)suspend followed by raid_dtr:
+	 *
+	 * MD's call chain md_stop_writes()->md_reap_sync_thread()
+	 * causes work to be queued on the md_misc_wq queue
+	 * not flushing it, hence the callback can occur after
+	 * a potential destruction of the raid set causing an oops.
+	 */
+	rs->md.event_work.func = NULL;
+
 	md_stop_writes(&rs->md);
 }
 
@@ -1684,6 +1695,13 @@ static void raid_resume(struct dm_target *ti)
 {
 	struct raid_set *rs = ti->private;
 
+	/*
+	 * See "Address a teardown race" in raid_presuspend()
+	 *
+	 * Reenable the worker function.
+	 */
+	rs->md.event_work.func = do_table_event;
+
 	set_bit(MD_CHANGE_DEVS, &rs->md.flags);
 	if (!rs->bitmap_loaded) {
 		bitmap_load(&rs->md);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: dm-raid: unsynced raid snapshot creation/deletion causes panic (work queue teardown race)
  2015-04-29 12:33 [PATCH] dm-raid: unsynced raid snapshot creation/deletion causes panic (work queue teardown race) heinzm
@ 2015-05-11 20:30 ` Mike Snitzer
  2015-05-12 10:38   ` Heinz Mauelshagen
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Snitzer @ 2015-05-11 20:30 UTC (permalink / raw)
  To: heinzm; +Cc: dm-devel

On Wed, Apr 29 2015 at  8:33am -0400,
heinzm@redhat.com <heinzm@redhat.com> wrote:

> From: Heinz Mauelshagen <heinzm@redhat.com>
> 
> This patch avoids oopses caused by a callback racing
> with the destrution of a mapping.
> 
> 
> Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
> Tested-by: Heinz Mauelshagen <heinzm@redhat.com>
> 
> 
> ---
>  drivers/md/dm-raid.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
> index 88e4c7f..fc4bc83 100644
> --- a/drivers/md/dm-raid.c
> +++ b/drivers/md/dm-raid.c
> @@ -1614,6 +1614,17 @@ static void raid_presuspend(struct dm_target *ti)
>  {
>  	struct raid_set *rs = ti->private;
>  
> +	/*
> +	 * Address a teardown race when calling
> +	 * raid_(pre|post)suspend followed by raid_dtr:
> +	 *
> +	 * MD's call chain md_stop_writes()->md_reap_sync_thread()
> +	 * causes work to be queued on the md_misc_wq queue
> +	 * not flushing it, hence the callback can occur after
> +	 * a potential destruction of the raid set causing an oops.
> +	 */
> +	rs->md.event_work.func = NULL;
> +
>  	md_stop_writes(&rs->md);
>  }
>  
> @@ -1684,6 +1695,13 @@ static void raid_resume(struct dm_target *ti)
>  {
>  	struct raid_set *rs = ti->private;
>  
> +	/*
> +	 * See "Address a teardown race" in raid_presuspend()
> +	 *
> +	 * Reenable the worker function.
> +	 */
> +	rs->md.event_work.func = do_table_event;
> +
>  	set_bit(MD_CHANGE_DEVS, &rs->md.flags);
>  	if (!rs->bitmap_loaded) {
>  		bitmap_load(&rs->md);

The subject of this patch is strange (snapshot?)

Anyway, what flushes the md_misc_wq before you set it to NULL?
Shouldn't that happen as part of presuspend?

Also, is it really safe to set this to NULL out from underneath MD?
Should a helper get exposed from MD with some extra locking?

Mike

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: dm-raid: unsynced raid snapshot creation/deletion causes panic (work queue teardown race)
  2015-05-11 20:30 ` Mike Snitzer
@ 2015-05-12 10:38   ` Heinz Mauelshagen
  0 siblings, 0 replies; 3+ messages in thread
From: Heinz Mauelshagen @ 2015-05-12 10:38 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: dm-devel



On 05/11/2015 10:30 PM, Mike Snitzer wrote:
> On Wed, Apr 29 2015 at  8:33am -0400,
> heinzm@redhat.com <heinzm@redhat.com> wrote:
>
>> From: Heinz Mauelshagen <heinzm@redhat.com>
>>
>> This patch avoids oopses caused by a callback racing
>> with the destrution of a mapping.
>>
>>
>> Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
>> Tested-by: Heinz Mauelshagen <heinzm@redhat.com>
>>
>>
>> ---
>>   drivers/md/dm-raid.c | 18 ++++++++++++++++++
>>   1 file changed, 18 insertions(+)
>>
>> diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
>> index 88e4c7f..fc4bc83 100644
>> --- a/drivers/md/dm-raid.c
>> +++ b/drivers/md/dm-raid.c
>> @@ -1614,6 +1614,17 @@ static void raid_presuspend(struct dm_target *ti)
>>   {
>>   	struct raid_set *rs = ti->private;
>>   
>> +	/*
>> +	 * Address a teardown race when calling
>> +	 * raid_(pre|post)suspend followed by raid_dtr:
>> +	 *
>> +	 * MD's call chain md_stop_writes()->md_reap_sync_thread()
>> +	 * causes work to be queued on the md_misc_wq queue
>> +	 * not flushing it, hence the callback can occur after
>> +	 * a potential destruction of the raid set causing an oops.
>> +	 */
>> +	rs->md.event_work.func = NULL;
>> +
>>   	md_stop_writes(&rs->md);
>>   }
>>   
>> @@ -1684,6 +1695,13 @@ static void raid_resume(struct dm_target *ti)
>>   {
>>   	struct raid_set *rs = ti->private;
>>   
>> +	/*
>> +	 * See "Address a teardown race" in raid_presuspend()
>> +	 *
>> +	 * Reenable the worker function.
>> +	 */
>> +	rs->md.event_work.func = do_table_event;
>> +
>>   	set_bit(MD_CHANGE_DEVS, &rs->md.flags);
>>   	if (!rs->bitmap_loaded) {
>>   		bitmap_load(&rs->md);
> The subject of this patch is strange (snapshot?)

Mike,
it was hit it with a test where a snapshot LV was created on a raid LV..

>
> Anyway, what flushes the md_misc_wq before you set it to NULL?

The work queue is empty when I set it to NULL, because recovery is still
ongoing. The OOPs is being triggered because md_reap_sync_thread()
being called from __md_stop_writes queues work again in case the worker
function is not NULL, hence causing it to be called when the raid_dtr() 
has teared
down the dm mapping already.

> Shouldn't that happen as part of presuspend?
>
> Also, is it really safe to set this to NULL out from underneath MD?

Rethinking based on your remark there may still be a race, because setting
the worker function to NULL  in raid_preresume() may  occur after an md 
worker
has queued event work for dm-raid already (e.g. in the cours of md error 
processng)
but md_misc_wq has not yet been run.

> Should a helper get exposed from MD with some extra locking?

A lightweight solution could be an MD recovery flag 
(MD_RECOVERY_DONT_CALLBACK ?) set
in raid_presuspend() preventing md_reap_sync_thread() from queueing work?

I.e.:
         if (mddev->event_work.func && 
!test_bit(MD_RECOVERY_DONT_CALLBACK, &mddev->recovery))
                   queue_work(md_misc_wq, &mddev->event_work);

Neil,
what do you think about this idea?

Heinz

>
> Mike

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-05-12 10:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-29 12:33 [PATCH] dm-raid: unsynced raid snapshot creation/deletion causes panic (work queue teardown race) heinzm
2015-05-11 20:30 ` Mike Snitzer
2015-05-12 10:38   ` Heinz Mauelshagen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.