Commit 8d24790e authored by Benjamin Marzinski's avatar Benjamin Marzinski Committed by Mike Snitzer

dm-delay: fix workqueue delay_timer race

delay_timer could be pending when delay_dtr() is called. It needs to be
shut down before kdelayd_wq is destroyed, so it won't try queueing more
work to kdelayd_wq while that's getting destroyed.

Also the del_timer_sync() call in delay_presuspend() doesn't protect
against the timer getting immediately rearmed by the queued call to
flush_delayed_bios(), but there's no real harm if that does happen.
timer_delete() is less work, and is basically just as likely to stop a
pointless call to flush_delayed_bios().

Fixes: 26b9f228 ("dm: delay target")
Signed-off-by: default avatarBenjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
parent 83637d90
...@@ -154,8 +154,10 @@ static void delay_dtr(struct dm_target *ti) ...@@ -154,8 +154,10 @@ static void delay_dtr(struct dm_target *ti)
{ {
struct delay_c *dc = ti->private; struct delay_c *dc = ti->private;
if (dc->kdelayd_wq) if (dc->kdelayd_wq) {
timer_shutdown_sync(&dc->delay_timer);
destroy_workqueue(dc->kdelayd_wq); destroy_workqueue(dc->kdelayd_wq);
}
if (dc->read.dev) if (dc->read.dev)
dm_put_device(ti, dc->read.dev); dm_put_device(ti, dc->read.dev);
...@@ -335,7 +337,7 @@ static void delay_presuspend(struct dm_target *ti) ...@@ -335,7 +337,7 @@ static void delay_presuspend(struct dm_target *ti)
mutex_unlock(&delayed_bios_lock); mutex_unlock(&delayed_bios_lock);
if (!delay_is_fast(dc)) if (!delay_is_fast(dc))
del_timer_sync(&dc->delay_timer); timer_delete(&dc->delay_timer);
flush_delayed_bios(dc, true); flush_delayed_bios(dc, true);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment